MVC Passing Data as Hidden (Not in URL, not as Hidden HTML) - asp.net-mvc

I'm using MVC 3 C#.NET.
Is there any way to pass values between pages (two different page with different controllers) without exposing the value in the URL or as hidden values? Is the last resort using a Session variable? Or would you recommend encoding the hidden field (ala ViewState style) and parse that to the controller?
I'm passing several values that I want hidden from the user as they might try to play with the values.
Any suggestions?

Simply use a POST and hidden fields in your form. POST fields do not show up in your URL only GET's. Always try to minimize the use of session variables, those should be used to store user login information, user settings, preferences, etc.

Simply persist this data in some backing storage on your server (could be a database or whatever backing storage you are using). I am not fan of a Session myself so I don't recommend it using it at all. If the user is not supposed to see or modify this data, then this data should not even be passed to the view. It should stay where it belongs => on the server.

I still used hidden fields, but encoded it to Base64, ala ViewState style. It obscures the real values for most users.

Related

Struts2 how to keep form values when navigating between pages?

I’m using struts2 + spring3 for my project. Please help me to resolve this problem.
In my app, (a.jsp) relate to --> (aAction.java).
From the main menu, user can access a.jsp. There are so many fields in the a.jsp that user need to key in data. In the middle of the page, user needs to go another page (b.jsp) to add some more details. (b.jsp page is not a popup window) After adding data to b.jsp, user needs to come back to a.jsp. How can I retain a.jsp page data?
Only one action use for both pages (aAction.java).
1) I can keep hidden variables in b.jsp and populate data again in a.jsp. But there are so many
fields in a.jsp. So this way is tedious.
Is there any way to handle this problem with bean scope? Or any other way to do?
There are several ways to do this
use redirectActions in struts.xml. When defining results you can set the type to redirectAction. Then you can redirect to another action and pass params that will be added as parameters to the url
http://struts.apache.org/release/2.1.x/docs/redirect-action-result.html
use localStorage instead of session storage. Limit is 5 MB. Care needs to be taken when using session storage as it can affect the server's performance
if you are using struts, you can make your own type converter for passing any object. Alternatively you could create an string array of the values you want to persist and pass it as a param in struts.xml (see above). Struts has built in type converter for persisting string arrays between pages/actions
you could also save them in cookies and then delete the cookies as soon as the values are not needed as there is a limit on the number of cookies browsers can support
I usually use session storage as a last resort for the reason mentioned above

Is ViewBag and ViewData also part of state management in asp.net mvc?

Can somebody please tell me that whether ViewData and ViewBag are also part of asp.net mvc state management or not?
Thanks
ViewBag and ViewData do not store state, but they can pass it to views to be rendered and stored.
What are ViewBag and ViewData?
ViewBag and ViewData are not state persistence mechanisms, but I believe they are part of State Management: they are mechanisms for passing data to a page which can then be persisted as state in the generated html. In this way they are part of the lifecycle of state, as they allow you to store state in your client side html using helpers such as #Html.HiddenFor or #Html.ActionLink.
In my answer to "storing a js value from 1 ActionResult to use in another ActionResult" I talk about how ViewBag and ViewData can be used to store state in the client html, and what the various options for state storage are.
As for what ViewBag is, it's actually a dynamic way of accessing ViewData, so ViewBag.MyItem = "foo"; and var valueEqualsFoo = ViewData["MyItem"]; will set and return the same string and can be interchanged.
What are they similar to?
ViewBag, ViewData are most closely connected to a View Model in an Action, where the model is passed to a View inside the Action using return View(viewModel);: all three techniques pass the state in memory into the html where it is sent to the client, to any intermediate caches, and "persisted" away from your server.
In a similar way, when a query string in a url is sent to a server in an http request it is a method of passing state, the actual state store is the ... anchor in the html. Restful URLs, and bodies for POST ajax requests, are the same in their definition and behaviour. ViewBag/Data pass the state from the Action to the html, which is passed to the client and stored, the query string or restful url then pass the state back to the server for use in the next Action invocation.
When should I use them?
It is hard to check for dynamic properties with a misspelling in your Razor code; it is easy to check if a property exists on a strongly typed view model. Therefore I believe you should use them very rarely. In my opinion it is preferable to create strongly typed view models rather than use ViewBag or ViewData. They might be fine for a quick and dirty solution, but those things tend to create Technical Debt. ViewBag is possibly ok for setting the page title.
Strongly typed View Models:
make it easier to use mapping with frameworks like automapper;
make views more testable; and
make it easier to create different views for different devices where you pass the same model to each view †
What are my options for state storage?
I said it here, and I'll say it again: There used to be at least Nine Options for Managing Persistent User State in ASP.NET, and many of those still apply in MVC. They all have different uses depending on how the state should be used. Generally server side code that is as stateless as possible is easier to test and debug.
Client side storage includes:
Entities passed back in the html result, and turned into:
Input fields
Hidden Fields
Javascript variables for use in ajax request POST bodies
Query string values, and paths in URLs (e.g. Restful URLs like /Product/1)
Older ASP.NET techniques that keep state in hidden html fields such as ViewState
Cookies
Html5 techniques such as Local Storage
Anti forgery tokens generated to prevent XSRF
Server side storage (directly related to ASP.NET and ASP.NET MVC):
Session (available through the Controller's Session property
Cache (available through the Controller's Cache property)
TempData
HttpContext["item key"]
Application (available through the Controller's HttpContext property as HttpContext.Application)
Web.config and Machine.config files (yes, these also hold state, it is just application wide) and therefore the WebConfigurationManager.AppSettings dictionary.
Server side storage (other):
Databases whether SQL or NOSQL
File storage
Message Queues such as WASB
Footnotes:
† We now have easy to use tools for responsive design which we can use when appropriate, but it is not always suitable: some views need to look entirely different on mobile but still use the same viewmodel as the large screen site.
Both of are Not !
State Management have 2 type
1: Client side , 2:Server side
Client side
Hidden Field
View State
Cookies
Control State
-Query Strings
Server side
Session
Application
If you want to difference for these, please look here
What's the difference between ViewData and ViewBag?
and
What is ViewData, ViewBag
In View Data, View Bag and Temp data we will carry data from controllers to view so it is a part of state management in MVC.
State management means preserves the state of controllers and webpage and objects and data.
This can be done by to ways:
Client Side State Management
Server Side State Management.
In Brief to know https://www.codeproject.com/Articles/492397/State-Management-in-ASP-NET-Introduction.

How should I preserve and repopulate form data when opening a sub-form?

In an MVC4 project, I have a form that contains a partial view which is an index view of languages studied at school. It is a default type view template index, with Add, Delete, Edit links per row etc. When you Add or Edit, it opens an Add or Edit view for a Language. After e.g. adding a language, the updated partial view is returned.
My problem is that if the user opens the Language form, edits and captures on the main form will be lost. I can't just do an Ajax save before opening the Language form, as the main form may only be partially complete and fail validation. What I am thinking of doing though is using an AjaxPreserve action that takes a FormCollection, and stores it in session (o on disk, or anywhere) and therefore no model binding and server validation is performed.
I then have two problems: I will need to disable client validation before calling the AJAX action, and I will need to repopulate the main form using the FormCollection I saved earlier. I think there should surly be some jQuery voodoo to disable client validation, but I am completely stumped on repopulating the form.
ALTERNATE SOLUTION: Instead of using 'sub-forms', I can use editor templates, in pop-ip forms, where the FK IDs are not required, but that us only in certain cases, so my question still stands.
Could you use something like Knockout where you create javascript model and bind it to a grid/dialog edit/template view. I would transform the whole data to a JS model, bind it to a table/grid and then track all changes on the client side. When all is done, just serialize the whole model back to the server and update the data store.
If this is an acceptable scenario, it will save you a lot of trouble.
Familiarity with Knockout is required, but if you've used it before, you will be able to solve this in a very clean and efficient way.
This example on the Knockout website gives an idea of what I'm trying to suggest. Editing, deleting, adding is done on the client side until you send all of the data back to the server. You will need to track flags for each object to know if it's added, edited or deleted.
http://knockoutjs.com/examples/contactsEditor.html
Simple make the sub request for adding language using Ajax and repopulate the dropdown or what ever way you are accepting language on the main form on sucessfully save.
*This will save a lot of effort. *
Why don't you just use javascript?
E.g. You have main form, that stores some data. And when you need to add something specific like languages you open popup using partial view, allow user to fill form, but when user press submit you intercept action with js, save stuff to javascript array/object or whatever else and maybe store it in a hidden field of main form - for final submit
var newData = new Object();
newData.Field1 = $("#yourField1");
...
lanuageData.push(newData);
$("#languageContainer").val(JSON.stringify(languageData));
...
DataAnnotation validation works here as well like:
$.validator.unobtrusive.parse("your_partial_view_container");
When you need to edit some object that was already added to js array - open popup and fill it up with element of you js array. So basically you do all CRUD on client-side, saving changes only on final submit.
To make your code in a conrolller more clear you can use custom model binder which deserialize some string field from JSon to List or any other kind of object -> so it can be validated on server side.
Would saving your values to local storage be acceptable? What about using TempData?

Redirect After Post in ASP.NET MVC

I am using the Redirect After Post pattern in my ASP.NET MVC application. I have
the following scenario:
User goes to /controller/index where he is asked to fill a form.
Form values are POSTed to /controller/calculate.
The Calculate action performs calculation based on input and instantiates a complex object containing the results of the operation. This object is stored in TempData and user is redirected to /controller/result.
/controller/result retrieves the result from TempData and renders them to the user.
The problem with this approach is that if the user hits F5 while viewing the results in /controller/result the page can no longer be rendered as TempData has been expired and the result object is no longer available.
This behavior is not desired by the users. One possible solution would be instead of redirecting after the POST, just rendering the results view. Now if the user hits F5 he gets a browser dialog asking if he wants to repost the form. This also was not desired.
One possible solution I thought of was to serialize the result object and passing it in the URL before redirecting but AFAIK there are some limitations in the length of a GET request and if the object gets pretty big I might hit this limitation (especially if base64 encoded).
Another possibility would be to use the Session object instead of TempData to persist the results. But before implementing this solution I would like to know if there's a better way of doing it.
UPDATE:
Further investigating the issue I found out that if I re-put the result object in TempData inside the /controller/result action it actually works:
public ActionResult Result()
{
var result = TempData["result"];
TempData["result"] = result;
return View(result);
}
But this feels kind of dirty. Could there be any side effects with this approach (such as switching to out-of-process session providers as currently I use InProc)?
Store it in the Session with some unique key and pass the key as part of the url. Then as long as the session is alive they can use the back/forward button to their heart's content and still have the URL respond properly. Alternatively, you could use the ASP cache, but I'd normally reserve that for objects that are shared among users. Of course, if you used the parameters to the calculation as the key and you found the result in the cache, you could simply re-use it.
I think redirect after post makes much more sense when the resulting Url is meaningfull.
In your case it would mean that all data required for the calculation is in the Url of /controller/result.
/controller/calculate would not do the calculation but /controller/result.
If you can get this done thinks get pretty easy: You hash the values required for the calculation and use it as the key for the cache. If the user refreshes he only hits the cache.
If you cant have a meaningfull url you could post to /controller/index. If the user hits F5 calculation would start again, but a cache with the hash as key would help again.
TempData is generally considered useful for passing messages back to the user not for storing working entities (a user refresh will nuke the contents of TempData).
I don't know of more appropriate place than the session to store this kind of information. I think the general idea is keep session as small as possible though. Personally I usually write some wrappers to add and remove specific objects to session. Cleaning them up manually where possible.
Alternatively you can store in a database in which you purge stale items on a regular basis.
I might adopt a similar idea to a lot of banks on their online banking sites by using one-time keys to verify all POSTs. You can integrate it into a html helper for forms and into your service layer (for example) for verification.
Let's say that you only want to post any instance of a form once. Add a guid to the form. If the form does not post back and the data is committed then you want to invalidate the guid and redirect to the GET action. If say the form was not valid, when the page posts back you need a new (valid) guid there in the form waiting for the next post attempt.
GUIDs are generated as required and added to a table in your DB. As they are invalidated (by POSTS, whether successful or not) they are flagged in the table. You may want to trim the table at 100 rows.. or 1000, depending on how heavy your app will be and how many rendered but not yet posted forms you may have at any one time.
I haven't really fine tuned this design but i think it might work. It wont be as smelly as the TempData and you can still adhere to the PRG pattern.
Remember, with PRG you dont want to send the new data to the GET action in a temp variable of some sort. You want to query it back from the data store, where it's now committed to.
As Michael stated, TempData has a single purpose -> store an object for one trip only and only one trip. As I understand it, TempData is essentially using the same Session object as you might use but it will automatically remove the object from the session on the next trip.
Stick with Session imho rather than push back in to TempData.

Make all form fields readonly in MVC

I am displaying 3 or more versions of a form. One version is an edit form to edit all fields. A second version will be a read only version of the same form which will be used to show all the same fields but with all fields having readonly="true" on the client side so that the user cannot enter data. The readonly fields need to use a different css style. This is to display archived data. I am already hiding the submit button so they can't submit but I want the form to look like it is readonly. A third version will have some fields readonly and some editable for a particular class of users that has limited editing privileges.
I am using ASP.NET MVC 1.0. How do I modify all (or a subset) of the fields displayed so they are readonly. I would like to iterate through the collection of fields in the controller and set them all to readonly and also set the correct css class. I don't want to have to put an if statement on every field in the .aspx file (there are 40-50 fields) and I'd prefer not to have this on client side so I can prevent users from modifying javascript/html to edit things they are not supposed to.
TIA,
Steve Shier
Keep in mind that even if you set the tags as readonly on the server side, users can still change them through a variety of means, and whatever the value on the form is before it gets sent back to you.
Certainly the easiest way is client-side with jQuery:
$(function() {
$('input, select, textarea').attr('disabled', 'disabled');
});
Or, you could do it in your View, but it's ugly. Off the top of my head, you would need some sort of bool passed into the View (via ViewData I suppose), and check that on each Input to see if you should add the disabled attribute. Not my idea of fun...
I would have different views that correspond to your states and then choose the view depending on which state you are in. You could also implement it with partials, breaking down the pieces so that you can easily include editable or read-only versions of the different sets of elements. The read-only view, then, need not even include a form element. You could also present the data in spans, divs, or paragraphs rather than as input elements.
Note: you'll still have to check whether the current user has the ability to update/create data in the actions that process form submits. Just because you limit the ability to view data in a read-only format, that won't stop someone from crafting a form post to mimic your application if they want. You can't rely on hiding/disabling things on the client to prevent a malicious user from trying to enter/modify data.
I usually use partial views to represent forms and/or parts of forms.
I can think of two simple ways to do what you need (as I understood it):
<% Html.RenderPartial(the_right_partial, model); %> where the_right_partial is either a value passed from the controller or a helper (in which case, the_right_partial(something));
pass a bool or enum paramether from controller representing editability and then using a helper to obtain the right htmlAttributes, like:
<%= Html.TextBox("name", value, Html.TheRightHtmlAttributesFor(isReadableOrNot)) %>;
There may be other ways, like creating new helpers for input fields which accept an additional isReadableOrNot arg (but it seems an overkill to me), or like mangling the html/aspx in some odd (and totally unreadable/unmaintainable way), but I'd not suggest them.
Notice that using html attributes like disabled is client side, and with tools like firebug it takes just two seconds to change them.
Others have already said it, but I also have to: always assume that the user will do his/her best effort to do the worst possible thing, so check the user rights to modify stuff on server side, and consider client side checks as a courtesy to the user (to let her/him understand that the form is not supposed to be edited, in this case).
Since I am trying to use a single partial for the different states of the form, I am thinking I will create helper functions which will display correctly based on the state and the user. The helpers will use a dictionary of fields that will indicate under which condition the field is read only. I will still have server side checks to make sure data is valid and the user is authorized to make changes.
Thanks for all of your ideas and help.
Steve

Resources