I'm trying to work out if there's a built in way in ASP.NET MVC to assign the form values that are POST'd back to the properties of the ViewModel that was originally sent to the View?
So I'm thinking along the ideas of decorating some of the properties in the ViewModel with an attribute and then reflecting over the ViewModel and using that name to extract values (and coerce) from the Form[] object.
However, I'd imagine that something like this was already built in and so don't want to re-invent the wheel here.
The problem that I'm trying to solve is that a user clicks a button on a form and the server validates the data and if there are errors we return the user to the form by using the same ViewModel to carry the data and thereby fill the values back into the form that the user originally entered.
(Yes, I'm also doing client side validation using JavaScript to make this lightweight but for security I have to repeat validation on the server.)
Ideas?
You can use UpdateModel or TryUpdateModel in your controller.
I recommend using one of the overloads in which you specify the fields to be updated.
This is discussed in detail on page 78 of the Wrox Professional ASP.net ebook (or echapter!)
I don't think MVC has anything like this built in, or at least I haven't seen anything. It would be nice though as many other MVC frameworks do this (struts for example).
Related
TL;DR
What are the best practices when using .NET Razor views and AngularJS?
Context
We are developing a public website (not an intranet application) using mvc4 with razor, and we weren't very familiar with client script, so we started with what we knew: jQuery.
But now things are getting more complicated and we'd like to switch to AngularJS.
On the .NET part, we use Razor templates and UIHintAttribute (plus some custom ones) to render the right html "control". We also add custom html attributes to give extra information to the jQuery part (like title for a tooltip....)
So we already use a declarative way of setting the user interface behavior, that's why AngularJS seems a good option.
Questions
Since we already have models defined server side, and since AngularJS also uses models, wouldn't it force us to duplicate code?
How do we deal with data binding feature, since we already do some binding server side (in the views). Should we make a completely asynchronous application, making AJAX calls from AngularJS to load data, or can we mix both?
Anything else we should be aware of when trying to use both of these technologies?
I did some research on Google, but I can't find detailed ways of mixing Razor views and templates with AngularJS... Perhaps that's just not a good thing to do?
We dealt with this issue for months when working with MVC plus another JavaScript framework (Knockout). Ultimately, if you're going to be using a client-side MV* framework for rendering your user interface, you will find that mostly ditching Razor is going to be your best bet.
Most of the major MV* JavaScript frameworks, including AngularJS, assume you will be maintaining UI state and rendering your user interface based on JavaScript models or view models. Trying to mix in server-side rendering is just not going to work very well.
That's not to say there is no use for MVC when it comes to developing an Angular application. You can still take advantage of some great features like ASP.NET Bundling and Minification. And sometimes it works really well to embed JSON directly into the page using a Razor view or partial as opposed to making an additional AJAX call.
As for models, you may want to take a look at Breeze.js. It's a JavaScript library for data access that goes great with ASP.NET on the server side to share model metadata.
We wrote our own data binding mechanism that synchronizes the angular.js model with a view model on the server side. The javascript model is generated from a JSON serialization of the server-side view model to avoid the duplicate code that you were talking about.
We are using SignalR to update the client's view model from the server.
Server-side changes of the C# view model properties are sent to the client as a packet containing the path to the property, e.g. Persons[42].Address.City, and the value itself, e.g. New York. The view model inherits a base class that takes care of generating the property path, so the actual view model looks quite clean and we can concentrate on business logic.
Client-side changes of the javascript view model properties are sent to the server in the same way. To catch the change events, we encapsulate all fields of the original javascript model in get/set properties where the setter sends the update packet to the server.
Server-side methods of the view model can be invoked in a similar way. All objects in the view model have an invokeMethod function that can be used like this: Products[42].Manufacturer.invokeMethod('SendEmail', 'mailsubject', 'mailbody'). This will send a packet to the server containing the method path Products[42].Manufacturer.SendEmail and the arguments as an array of ['mailsubject','mailbody'].
In conclusion, the html view (kind of) binds to the view model on the server side where other systems, such as regular Razor views can work on the same objects.
The source code can be found here: SharpAngie.
I am currently working with integrating a classic asp site with MVC3. I have some questions on some areas of the integration that I would like some feedback on.
Firstly, I have a asp page posting to an MVC controller action. I have very little scope to modify the asp page. I want to take the form fields posted from the asp page and map them in to a model object. The posted values have obscure names such as "my_name" which I want to map to Name property on the model object. Is the best way of doing this via a Model Binder or is there an alternative?
Next question I have is a follow on from the previous, I am concerned with any cross site scripting so want to check the values of the posted variables to be valid and contain no strange characters etc. Is there something built in to MVC3 that does this out of the box?
When the asp page posts to the controller action, I would like to show a waiting icon while the controller action is processing as the controller action could take 10 seconds plus as it must call external systems etc. Therefore I don't want the post to seem as its hanging. Is it possible to wire up the controller action to return a view with a waiting icon, while the main body of the action is processing in the background and once complete redirects to another page?
Is the best way of doing this via a Model Binder or is there an
alternative?
The best way of doing is a model binder. You can have a custom model binder to take care of the ASP scenario that maps the my_name to Name. Mostly you should have a separate action to handle the requests coming from classic asp and you can link the custom model binder to only this action.
Is there something built in to MVC3 that does this out of the box?
The request validation is enabled as default in MVC. So if an user tries to post a script block to the action MVC will throw exception. Of course you can switch off request validation by decorating the action with ValidateInput(false) if you need.
For long running actions you have to use asynccontrollers.
In the application I'm developing in ASP MVC 3 I have the following scenario. I have some properties of the model that I wanna use after the page makes a request, however when the post request is done they arrive as null since they are not bound to any control in the view form.
For what I've read this is the expected behaviour of ASP MVC and people recommend to use a #Html.HiddenFor() to be able to receive them, but I don't want this information to be available to user in case he selects "View source" from the browser.
In JSF I remember that you could use the #ViewScope annotation for this scenario, but is there something similar in ASP MVC? For what I've read saving them in the ViewData property will not work either and I do not want to use the Session because this properties will only be relevant in this particular view.
If I understand your question correctly, you may be looking for something like TempData.
You can read about it here:
http://blogs.teamb.com/craigstuntz/2009/01/23/37947/
A more recent post can be found here:
http://codeoverload.wordpress.com/2011/05/29/controller-tempdata-in-asp-net-mvc-3/
Is there a way to keep information between post backs in MVC2 without utilizing Session variables or the query string?
You mean like the view state from .NET Web Forms? Technically there is, although it isn't recommended - you're much better off utilizing models and posting the model data to the server and pushing the model back into the view.
This will work well but if you're needing something as stateful as the WebForms ViewState, I would recommend doing your project in WebForms or use the session to save your models.
Edit: Build your form that posts (or gets) data back to the same page. Then in your controller, have a method like this.
[HttpPost]
public ActionResult LoginUser(LoginViewModel model)
{
//work on the model here
return View(model);
}
This will push the form data that the user just submitted back into your view. Then have an Html helper like this in your view.
<%: Html.TextboxFor(m => Model.Username) %>
There are a slew of excellent resources on the web about using html helpers with models. Google around and you'll come across them.
You could use Hidden Form fields to POST the values back to the server with each form submission.
Other alternatives include a cookie or Http Cache - what is stopping you using session?
As a high level concept, you should rely as little as possible not only on Session to store your state, but on statefulness in general in a web application. The idea is that the web itself is stateless by design, and when designing software on that paradigm the software should be designed to embrace a stateless nature.
More specifically, using a ViewModel gives you a strongly typed representation of the data needed for your view to pass down to the client. Pieces of that data which hold information about the state of a given request which can be made from that view can be added to the view in probably a number of ways, but the two most immediate ones are:
As hidden form field elements
As parts of URLs for requests
Check out the NerdDinner tutorial for a standard approach to using either ViewData or a strongly-typed ViewModel. Some Google searches will, as always, yield more information and tutorials. But note specifically where the tutorial uses the ViewModel properties in the view. These can be used anywhere in the rendering of the HTML, either in the HTML helpers or in manually constructing the tags.
Additional interesting reading regarding the statelessness of the web (and this whole not-as-new-as-many-people-seem-to-think REST thing) is the article: How I Explained REST to My Wife.
If your main issue with the Session variables is of a practical nature (want something that works for a single request, not needing to worry about cleaning it up etc) rather than a requirement to not use Session then use the TempData dictionary. It deals with putting information in the Session for a single request only and the framework will automatically remove it for you afterwards.
I am learning ASP.NET MVC, and ran across a video on the asp.net/mvc website that showed how to retrieve a value from a textbox after a postback. In the video the author simply grabs the value from the Request object in the controller.
It seems like this breaks the separation of concerns concept? By doing this the controller is now dependent upon the presence of a Request object which won't exist if one runs unit tests against the controller.
So I assume this is an incorrect way of retrieving form data on a postback. What is the correct way? Once I am in my controller, how do I get access to the postback data?
It seems there should be some intermediate step that essentially pulls the data from the postback and packages it into a nice object or some other format that the controller would then used?
The data should be posted back to your Model or ViewModel. Your controller method that handles the POST will expect the model to be provided as a parameter.
Here is a blog entry that gives an example
Using model binding, MVC can populate data coming from the form data, the query sting, cookies, and a number of other sources directly into your object model or other paramters defined as parameters to your action methods in the controller.
There's too many details of how this works to summarize here, but it is the cornerstone of the power of ASP.NET MVC.
Check out Models and Validation in ASP.NET MVC as a good starting point. You'll find tons of other resources around MVC model binding out there.
I've really liked Steven Sanderson's Pro ASP.NET MVC 2 Framework if you prefer physical books.