MVC why is UpdateModel sometimes used in Edit and sometimes not - asp.net-mvc

I'm new to MVC and I've been looking through a bunch of examples.
For the HttpPost on some edits they call UpdateModel(entity).
In other examples such as:
http://www.asp.net/mvc/tutorials/mvc-music-store-part-5
UpdateModel(entity) isn't called at all.
What's the point of calling this function when it appear unneccessary in MVCMusicStore?
Apparently it " Updates the specified model instance using values from the controller's current value provider."
However I've found from the MVCMusicStore example the updated values are already posted through?
Could someone please explain this to me?

There should be no reason for you to use UpdateModel in the newer version of ASP.NET MVC
Originally it was provided because when you posted your data back to the action on your controller, a FormsCollection would be passed in to to the action and then a call to UpdateModel(entity) would be required.
However in newer versions of ASP.NET MVC the concept of ModelBinding has been introduced which will allow your actions to define a .net object to be passed in to your action methods and the model binder will take care of "binding" the values to the model.
To be completely honest, I'm not sure why they don't just deprecate the UpdateModel() method because AFAIK it's completely redundant.

Use UpdateModel for PATCH semantics. From RFC5789:
The PATCH method requests that a set of changes described in the
request entity be applied to the resource identified by the
Request-URI.
This means you are making modifications to an existing resource (e.g. from the database).
Use the object as action method parameter for PUT semantics.
The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI. In a PUT request, the enclosed entity
is considered to be a modified version of the resource stored on the
origin server, and the client is requesting that the stored version be
replaced.
In practice, there's not much difference if the request contains values for all of the resource members. But if the request only contains values for a subset of the resource members, in PATCH the other members are left unmodified, and in PUT are set to their default value (usually NULL).

i don't think ModelBinding is only introduced in newest version of asp.net mvc (newest version is 3). it was present at least in v-2 so far as i can tell. when you call the updatemodel you call Modelbinding explicitly. when you receive at as action method parameter Modelbinder is called implicitly.
In Edit scenario updateModel is used when we fetch original entity from db and tell controller to update it using UpdateModel like
public ActionResult Edit(int id)
{
var entity = db.GetEntity(id);
UpdateModel(entity);
db.SaveChanges();
}
Other scenario is when you are not fetching db entity but ModelBinder gives you an entity created from form fields etc. and you tell you db that object is already there and it has been modified outside the db and you better sync with it like in MusicStore tutorial.

Related

Can I pass data directly from GET to POST serverside for Create() methods in MVC4 Controllers?

Based on another question:
Creating a Child object in MVC4 - Parent's information not being passed to Create() controller
Does MVC provide a mechanism to send data from the HttpGet Create() to the HttpPost Create() without going through the client? If I need to send some data to the Post method that is meaningless to the client, how can I avoid cluttering the Views and over-exposing model properties to potential attackers?
Your GET and POST actions are just methods on a class. It really doesn't sound like there's any reason to use POST here, if your only concern is to execute a block of code under certain conditions.
Change your POST (drop the attribute) and make it a private method so it is inaccessible to the client. In your GET, do whatever checks you need to do, then invoke the method.
If you do need to expose the POST, refactor the code in question out to a seperate private method that you can call from either GET or POST. A better implementation would be a separate class with the method located there for reuse/testing/SoC.
Just a caution if you are working with a DB here...while there are some legitimate reasons to write to the DB during a GET, note that this is not the indempotent nature of the GET in most circumstances (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html).
Cheers.
Yes - as I mentioned in the other answer you can use TempData - however you don't need this. You are using nothing but an id and a name from your entity, just pass only those in the view model. You don't need the full entity.
On the server side ensure your user has access to those records. For example if I was editing a Customer record, I'd ensure the current user has access via something like:
var currentUsersCompanyId = GetCurrentUserCompanyId();
ctx.Customers.Single(o=>o.CustomerId = customerId and currentUsersCompanyId == customerId)
There are a variety of ways to do this based on how you control permissions - and third party platforms for .net such as Apprenda that help do this more automatically behind the scenes.

MVC4 Action method AutoMap actionfilter fails to convert the view model to domain model

so, I've seen this working on a previous project in MVC3, so wondering if a) i've screwed it up, or b) MVC4 is doing something different (can't see it would be).
I have a model bound Razor view which submits to a controller action method (as is the way with MVC)
post action method:
[HttpPost]
[AutoMap(typeof(MyViewModel), typeof(MyDomainObj))]
public void PostAction(MyDomainObj obj)
{... etc.. etc..
The action filter eventually does something like this:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var model = filterContext.Controller.ViewData.Model;
NOTE: In Jimmy Bogard's example he used OnActionExecuted which I also tried..
The key issue I'm having is that at the pint where we get the "model" variable from the context, it's null. If I look at the filterContext.ActionParameters whilst debugging I can see a MyDomainObj instance!! which appears to (because it happens to have a prop name in common with the MyViewModel type) have been mapped from my form data!
So.. yes if I had MyViewModel type as the parameter to this method, then the param would be properly populated from the submitted form. But. I don't want to do that, I want to (and have done before based on JB's succinct how-to) converted the view model to domain model as part of the action executed/ing and then been able to just hit save on my domain model.
Summary - why is my ViewData.Model null on the post action filter?
Jimmmy also has/had a couple of ideas on how to implement post actions, along with another guy Matt Honeycutt who shares his view on how to do posts. I also believe Jimmy has gone in the direction of using explicit mapping in his get requests instead of attributes, as it can be hard to inject any extra code you need after mapping.
http://lostechies.com/jimmybogard/2011/06/22/cleaning-up-posts-in-asp-net-mvc/
http://trycatchfail.com/blog/post/Cleaning-up-POSTs-in-ASPNET-MVC-the-Fail-Tracker-Way.aspx
For a post you really want a couple of things imo, the original Entity and the Form Data. You could load the entity like you do for the GET request and do normal model binding to get the form data (remember you can accept a different model for post backs than you spit out in your view) then make the changes in the action.
Of course this would require using AutoMapper in your action, which you seem to be trying to avoid. But unless you write a custom model binder then you're not going to magically get the formdata in a model as the built in one looks at the action paramters to figure out what to bind. For this reason i'd recommend not using a domain model as a parameter for an action, as it may fill out fields that you don't wish it to.
I've also seen Jimmy using a ModelBinder to do something similar to your AutoMapGet, which may be another alternative method, but I'm guessing you've seen that post.
My standard post takes Matt's approach, moving the validation out into a global attribute so it can't be forgotten (there are some downsides to this) then accepting a new view model explicity for the form data, then I explicity load the entity, use automapper to update it and call save. Most the actions only end up being about 5 lines long.
I do avoid using the static methods on AutoMapper and pass a IMapper in via constructor injection. This allows me to make it a bit more testable if I really need to, however the methods are normally so simple the tests don't add all that much value.

How to handle hidden fields in MVC forms?

I have a FormViewModel that handles different fields. Many of them have not to be presented to the user (such as modified_date, current_user_id) so I am using hidden fields to respect the FormViewModel structure. When submitted they are passed to the controller's action and correctly saved to the DB but I'm asking: is it the best way to do in ASPNET MVC? I would have preferred to define them in FormViewModel and using only the fields to be modified instead of showing also the non-modifiable as hidden fields.
Is there a better way to do it?
If these fields are not being touched by the user than I would do this;
Create a FormViewModel with only the fields that are relevant. Also the primary key.
The primary key still needs to be on the page me thinks.
Then in the controller you accept the FormViewModel as the argument, you then load the actual model and update, validate fields as required and save the model.
The above is simplistic and you'll have more layers but you should get the idea
I think you can do a few things to make your life a little easier:
Let the URL (and the routing mechanism) give you the id (the primary key of whatever you are trying to edit)
You can have a URL like '/Student/Edit/1' Routing will ensure that your Action method gets the id value directly.
Have 2 action methods to handle your request. One decorated with [HttpGet] to render the initial form to the user (where you just retrieve your object from the repository and pass it on to your View) and a [HttpPost] one to actually handle the post back from the user.
The second method could look something like:
[HttpPost]
[ActionName("Edit")]
public ActionResult EditPost(int id) {
...your code here...
}
Retrieve the actual record from the repository/store based on the id passed in.
Use the UpdateModel function to apply the changes to the database record and pass on the record back to your repository layer to store it back in the database.
However, in a real world application, you will probably want separation of concerns and decoupling between your repository and your view layer (ASP.NET MVC.)
If they are part of the model, the method you are using is perfectly fine. You even have a helper method in HtmlHelper.HiddenFor to output the hidden field for you. However, if the values are something like modified date or current user, you'd might be better suited passing those along from your controller to a DTO for your data layer. I'm making some assumptions about what you're doing for data access, though.
The risk with storing data which shouldn't be modified in hidden fields is that it can be modified using a browsers built in/extension developer tools. Upon post these changes will be saved to your database (if that's how you're handling the action).
To protect hidden fields you can use the MVC Security Extensions project https://mvcsecurity.codeplex.com.
Say the field you want to protect is Id...
On you controller post method add:
[ValidateAntiModelInjection("Id")]
Within your view add:
#Html.AntiModelInjectionFor(m => m.Id)
#Html.HiddenFor(m => m.Id)
On post your Id field will be validated.
Create a FormViewModel with only the fields that are relevant. Also the primary key.
The primary key still needs to be on the page me thinks.
Then in the controller you accept the FormViewModel as the argument, you then load the actual model and update, validate fields as required and save the model.
The above is simplistic and you'll have more layers but you should get the idea

What is "posted" in ASP.NET MVC applications?

As I review more code and blog posts from lots of MVC sources, I still haven't wrapped my mind around what is "posted" when a request is made. I realize MVC doesn't support post, but I'm having trouble finding resources that can explain it well enough to understand.
Inside the controller's public ActionResult nameOfAction(what the heck goes here?) { ... } what are my parameters?
Sometimes it looks like Visual Studio scaffolds (int id, MyObject myobject) for an Edit-style action--it includes something from my model, but not always.
Sometimes, it's (int id, FormCollection collection) for a delete-style action. Why not use the modeled object here? Is a FormCollection object always "posted"?
Sometimes, I see (RouteInfo routeInfo) which isn't recognized in my MVC2 Intellisense (is this MVC1 only or something?)
How can/do/should I establish these parameters? I think this will help me a lot at design time.
What gets post back from a form in MVC is the form data which includes each form element in a keyvalue pair.
If you only need this information then you would use:
public ActionResult nameOfAction(string name, string lastName, string etc)
MVC has some smart data model binding which takes the form data and automatically creates an object which is part of you domain model. For instance it could automatically create a Person object with the provided form data.
I believe there is a security concern with this as a user of your site may post data which is not part of your form and guess what your models are to inject their own data.
I dont think this is a massive issue though and this is the way I would go.
I think you can use the anti-forgery helper to prevent users from posting back data which is not allowed in a form. anti-forgery
Use strongly typed views with a view-model and the strongly typed helpers. Then when you POST, you should get an instance of that view-model out.

How to update Model in MVC

I'm wondering how you keep a constant value of the Model in an ASP.NET MVC framework. Like when adding something to the Model through the view. You go back to an action in the controller but where do you keep the Model? Is it a private in the controller? or is it passed back and forth from the view to the controller because if it gets big then you are passing alot of data back and forth to add/delete a single item from the Model.
Also any small examples to show this?
Thanks
What are you referring to? Are you meaning a database table loaded up into an object such as Ruby on Rails's ORM -- typically the 'Model' is a series of interfaces or domain objects that load data into objects from the database .. or more simply just the database period.
Please be more specific. There are many MVC frameworks and many different kinds of 'Models'
I think you should check out a ASP.NET MVC tuturial like NerdDinner (from "Professional ASP.NET MVC 1.0"). Scott Guthrie has posted a html version of the tutorial on his site. It's a fairly simple site that they build in the tutorial, and is a great intro to ASP.NET MVC (in my opinion).
There are also some good tutorials on the ASP.NET site.
Hope these help you with .NET MVC, it's a great framework to use!
You can pass the model to the page and you can then use UpdateModel(model name) within your controller.
Each member in the model must be a property with a getter and a setter.
On the page you can hold the data in say a hidden field if you need to maintain the value outside of state.
If you have problems using UpdateModel then you can use the following in your controller;
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyAction(int? id, FormCollection collection)
{
string commentText = collection["myFieldName"];
}
This will normally get your values from the model.
Hope this is what you were asking.
Think of the model as a data transfer object. In a list, display only or edit page, you pull it out of a data layer as a single object or a list of objects. The controller passes it along to the view and it gets displayed.
In the case of an insert, a new data transfer object is instantiated upon post back and is updated with the posted values. Then sent back to the the data layer for persistence.
In the case of an edit, it comes from the data layer on the HTTP GET request and is used to pre-populate the HTML form. Then on post back, the data transfer object gets updated with the posted values and sent back to the the data layer for persistence.
Definitely checkout NerdDinner or Stephen Walther's samples.

Resources