Rectangle 27 2

Model binding works by binding the key/value pairs sent by the browser in a form post to model properties (or view data). A form input's name attribute is what is used as its key in the form data submitted in a POST request.

When you use HTML helpers to render form fields, the framework automatically generates the appropriate name attributes required to ensure that the field will bind properly to the property specified in the expression you pass to the helper.

If you change the name, you break the only connection between the form input and the property it binds to.

Hi @AntP, that makes a lot of sense but then I don't understand why they would provide a way to change the name as I did then, Is there a way I can change the actual names display on the HTML source without breaking up the binding mechanism?. Thanks.

That mechanism is for specifying any HTML attribute - it's not specifically for changing the name attribute. If you tell the framework you want to override the name attribute, the framework should (and does) defer to your judgment. You might well have a very good reason for doing so (in fact, in more complex binding scenarios the framework is often not quite clever enough to generate the right name itself and you have to give it a helping hand).

Why do you want to change the names in the HTML source? Posting form values under specified names is a standard HTML convention. If you just want to hide the names of the properties, just use meaningless names (and apologise to your colleagues). If that's not good enough, you'll need to delve deeper and look into custom model binding. I don't really see what this achieves, though.

I thought that exposing the properties of my model or viewmodel on the HTML source could be somewhat unsafe that's it. Plus l have this habit to put an identifier of the type of the object along with a similar name of the property on HTML objects so that's why.

You should build your web app under the assumption that anyone can put whatever values they want in your view models on a form post - because they can. As long as you account for that, there's nothing unsafe about exposing the names. The bigger issue is making sure that you don't have any view model properties that can be used maliciously.

c# - Model binding isn't working when htmlAttribute Name is changed on...

c# asp.net-mvc asp.net-mvc-4 model-binding
Rectangle 27 3

Generally, complex objects are passed in the HTTP body with verbs that support it such as POST and PUT. The body content must pass Model Binding validation. That basically means that if it's a POST request with Content-Type: application/json, it must deserialize from JSON into MyViewModel. If the content is XML, it must deserialize as XML.

General convention is to have all the primitive types that can be found in the URL path, query, and headers first, then one complex type from the POST (or PUT) body after that. I believe it's possible to put complex types elsewhere, but then you're getting into type converters and custom attributes which you should probably hold off on if you're a beginner.

Why is this second method adorned with [HttpPost] when the first method does not require any attributes? Are there any guidelines on when to use [Http] attributes and when not?

"[HttpPost]" is telling the routing engine that this method overload is only available via HTTP POST. Attempting to PUT /home/index with a body will fail with 404 Not Found, in this case. The parameter-free version of Index() doesn't require it because it can work with any HTTP verb, including GET, POST, and PUT.

c# - Understanding [HttpPost], [HttpGet] and Complex Actionmethod para...

c# asp.net asp.net-mvc asp.net-mvc-4
Rectangle 27 3

Generally, complex objects are passed in the HTTP body with verbs that support it such as POST and PUT. The body content must pass Model Binding validation. That basically means that if it's a POST request with Content-Type: application/json, it must deserialize from JSON into MyViewModel. If the content is XML, it must deserialize as XML.

General convention is to have all the primitive types that can be found in the URL path, query, and headers first, then one complex type from the POST (or PUT) body after that. I believe it's possible to put complex types elsewhere, but then you're getting into type converters and custom attributes which you should probably hold off on if you're a beginner.

Why is this second method adorned with [HttpPost] when the first method does not require any attributes? Are there any guidelines on when to use [Http] attributes and when not?

"[HttpPost]" is telling the routing engine that this method overload is only available via HTTP POST. Attempting to PUT /home/index with a body will fail with 404 Not Found, in this case. The parameter-free version of Index() doesn't require it because it can work with any HTTP verb, including GET, POST, and PUT.

c# - Understanding [HttpPost], [HttpGet] and Complex Actionmethod para...

c# asp.net asp.net-mvc asp.net-mvc-4
Rectangle 27 3

I think that it would help if you had a better understanding of how model binding works when you post back to an action method. In most cases, it is unecessary and inefficient to pass a view model as a parameter to a POST action method. What you are doing is loading the view model into memory twice when you pass your view model as a parameter (assuming a strongly typed view). When you do a post back the model becomes part of the form collection (through model binding) in the request object in the BaseController class that every controller inherits from. All that you need to do is to extract the model from the Form collection in the Request object in the BaseController. It just so happens that there is a handy method, TryUpdateModel to help you do this. Here is how you do it

[POST]
public ActionResult Save()
{
    var saveVm = new SaveViewModel();

    // TryUpdateModel automatically populates your ViewModel!
    // TryUpdateModel also calls ModelState.IsValid and returns
    // true if your model is valid (validation attributes etc.)
    if (TryUpdateModel(saveVm)
    {
        // do some work
        int id = 1;
        var anotherSaveVm = GetSaveVmBySomeId(id);

        // do more work with saveVm and anotherSaveVm
        // clear the existing model
        ModelState.Clear();
        return View(anotherSaveVm);
    }
    // return origonal view model so that the user can correct their errors
    return View(saveVm);
}

I think that the data in the form collection contained in the request object is being returned with the view. When you pass the model back to the post action method as a parameter, I believe it is passed in the query string (see Request.QueryString). Most of the time, it is best to only pass one or two primitive type parameters or primitive reverence types such as int? to an action method. There is no need to pass the entire model as it is already contained in the Form collection of the Request object. If you wish to examine the QueryString, seee Request.QueryString.

asp.net - Why is it that when I pass a Model to my .Net MVC 4 Controll...

asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4
Rectangle 27 2

Binding will only occur for fields that are actually used. If you are not using the request property in your view, might be better to just have the ID in a hidden input and load again on server in your POST. For the state, just add bool property to your model.

Hmm, request is an object tho, not sure what it would stick there. Did you look at actual HTML? In any case, why send all the stuff of whatever Request object is when you only use the state? And possibly ID on the POST.

c# - Pass ViewModel from HttpGet Action to HttpPost Action - Stack Ove...

c# asp.net-mvc asp.net-mvc-5
Rectangle 27 0

Generally, complex objects are passed in the HTTP body with verbs that support it such as POST and PUT. The body content must pass Model Binding validation. That basically means that if it's a POST request with Content-Type: application/json, it must deserialize from JSON into MyViewModel. If the content is XML, it must deserialize as XML.

General convention is to have all the primitive types that can be found in the URL path, query, and headers first, then one complex type from the POST (or PUT) body after that. I believe it's possible to put complex types elsewhere, but then you're getting into type converters and custom attributes which you should probably hold off on if you're a beginner.

Why is this second method adorned with [HttpPost] when the first method does not require any attributes? Are there any guidelines on when to use [Http] attributes and when not?

"[HttpPost]" is telling the routing engine that this method overload is only available via HTTP POST. Attempting to PUT /home/index with a body will fail with 404 Not Found, in this case. The parameter-free version of Index() doesn't require it because it can work with any HTTP verb, including GET, POST, and PUT.

c# - Understanding [HttpPost], [HttpGet] and Complex Actionmethod para...

c# asp.net asp.net-mvc asp.net-mvc-4
Rectangle 27 0

You will need to do some custom model binding to check the request object and act accordingly (adding modelstate errors, etc...) Here is a post related to custom model binding that should be beneficial.

Once in the custom model binder you can add code in the CreateModel method similar to this:

Dim request As HttpRequestBase = controllerContext.HttpContext.Request
If Not request.Form.AllKeys.Contains("YourCheckBoxName") Then
     bindingContext.ModelState.AddModelError("AnError", "You must check the box first")
End If

Thank you, and that's very interesting. I hadn't heard of doing that before.

@AnnL. Additionally, if you're looking for just a client side solution, you could create a ViewModel that essentially extends your model, make the view take your new ViewModel instead of the Model and add the "checkbox" fields as properties to the ViewModel. You could then use the default model binding included with MVC. See this link for more info: geekswithblogs.net/michelotti/archive/2009/10/25/

asp.net mvc - validating input fields that aren't part of the model - ...

asp.net-mvc asp.net-mvc-3 validation
Rectangle 27 0

When data is posted by to the controller, the MVC framework handles the binding of the request data to your model. Have a look at this link

When it is trying to instantiate your ViewModel, it is probably using the default parameterless constructor for your Parent class, and whatever the actual data being sent back, it cannot assign it to the properties as they don't exist within the Parent class.

You can create your own custom model binder which might solve your problem. Or you could potentially create all the properties in the Parent class, and have different named EditorTemplates.

@Html.EditorFor(x => Model.Parent, "ChildATemplate")

@Html.EditorFor(x => Model.Parent, "ChildBTemplate")

As a general rule it is a good idea to stick to the rule, "One View, One ViewModel", even if it feels like duplication at first. It makes it clear exactly what data is being sent out from the server and exactly what data is being returned.

If 'Parent' represents a complex object, perhaps one that that is persisted into a database and is interacted with from several views, then you can always have an intermediate tier which handles converting data from the view model to your complex class.

Rather than using inheritance, why not accept that you need to duplicate a little of the shared values, and create a class for each question type?

public class QuestionTypeA 
{
    public int ID { get; set;}
    public string Name { get; set; }
}

public class QuestionTypeB
{
    public int ID { get; set;}
    public DateTime Date { get; set; }
}

public class QuestionTypeC
{
    public int ID { get; set;}
    public int NumericData { get; set; }
}

public class ViewModel
{
    public List<QuestionTypeA> QuestionAs { get; set; }
    public List<QuestionTypeB> QuestionBs { get; set; }
    public List<QuestionTypeC> QuestionCs { get; set; }
}

The example I gave was simplified. Imagine you have not 2 or 3 types, but 13 or more. Now you need 13 separate classes (with duplicated properties), 13 lists... and since in the end I need one ordered list, now those lists probably need to be dictionaries or something to keep track of order. It is NOT a reasonable suggestion, in my case, to make each question a specific type and not use inheritance at all. A model binder sounds a lot better and I'm trying that out.

I'll accept this answer, as creating a custom binder is indeed the way to go.

c# - @Html.EditorFor doesn't return specific types to the controller -...

c# model-view-controller asp.net-mvc-6
Rectangle 27 0

You can try having a separate viewmodel, with properties for the list of options and the selected option. In the GET request action method, you can populate this list and render the view, and in the POST action method, you can exclude this property during model binding, so that only the selected item property will get bound. Thus, you don't need ViewBag or routeValues or querystring parameters, and your URL will always look clean.

public class ViewModel
{
    public int SelectedId { get; set; }
    public Dictionary<int,string> OptionList { get; set; }
}

And then in your view,

@Html.DropDownListFor(model => model.SelectedId, new SelectList(Model.OptionList, "Key", "Value"), null, null)
GET
Dictionary<int,string> OptionList = GetOptionList(); // Populate from DB
return View(new ViewModel { OptionList = OptionList });
[Bind(Exclude="OptionList")]
POST

I don't really understand your example. Do you have any code example or online documentation to clearly understand this and how to implement it ? I initially not used the ViewBag but someone suggest me the ViewBag in this post stackoverflow.com/questions/23563138/creating-a-dropdownlist/

c# - DropDownList without value at the PostBack - Stack Overflow

c# asp.net-mvc razor
Rectangle 27 0

View's don't have anything to do in POST request and model binding

When you have strong type views, model type is barely used to have the simplicity of code intellisense in view's code (so you can use lambda expressions like in your example).

But when you POST data back, nothing gets checked against the view. It gets checked against controller action parameters though. And if there's a parameter with a certain custom model binder type, that particular model binder is used to process incoming data.

But to answer your question: TextBoxFor checks your strong type view's model and generates particular textbox with correct name attribute. So data from it will be posted back under the correct form field name.

To go even deeper. It's the view engine that parses view's ASPX code and runs all server side scripts including Html.TextBoxFor() call.

Asp.net mvc 2 model binders what's behind scene - Stack Overflow

asp.net asp.net-mvc asp.net-mvc-2 modelbinders
Rectangle 27 0

That's because HTML helpers such as TextBoxFor first look in the ModelState when binding their values and only after that in the model. So if in your POST action you attempt to modify some value that was part of the initial POST request you will have to remove it from the ModelState as well if you want those changes to take effect in the view.

This behavior is intentional and it is by design. This is what allows for example to have the following POST action:

and yet inside the view you get the values that the user initially entered in the input fields.

There's also the ModelState.Clear(); method that you could use to remove all keys from the modelstate but be careful because this also removes any associated modelstate errors, so it is recommended to remove only values from the ModelState that you intend to modify inside your POST controller action.

All this being said, in a properly designed application you should not need this. Because you should use the PRG pattern:

[HttpPost]
public ActionResult Index(MyViewModel model)
{
    if (!ModelState.IsValid)
    {
        // there was some error => redisplay the view without any modifications
        // so that the user can fix his errors
        return View(model);
    }

    // at this stage we know that the model is valid. 
    // We could now pass it to the DAL layer for processing.
    ...

    // after the processing completes successfully we redirect to the GET action
    // which in turn will fetch the modifications from the DAL layer and render
    // the corresponding view with the updated values.
    return RedirectToAction("Index");
}

asp.net mvc 3 - How to update the textbox value @Html.TextBoxFor(m => ...

asp.net-mvc-3 html.textboxfor
Rectangle 27 0

As Filip mentions in that post ReadAsStringAsync or ReadAsByteArrayAsync methods buffer the request content internally. This means that even if your incoming request's stream type is a non-buffered stream, you could safely do a ReadAsStringAsync/ReadAsByteArrayAsync at a message handler for example, and also expect the model binding to work fine.

By default, a request's stream is buffered in both webhost and selfhost cases. But if you would like to check if using ReadAsStringAsync/ReadAsByteArrayAsync and model biding works fine even in non-buffered mode, you can do the following to force non-buffered mode:

public class CustomBufferPolicySelector : WebHostBufferPolicySelector
{
    public override bool UseBufferedInputStream(object hostContext)
    {
        //NOTE: by default, the request stream is always in buffered mode.
        //return base.UseBufferedInputStream(hostContext);

        return false;
    }
}

config.Services.Replace(typeof(IHostBufferPolicySelector), new CustomBufferPolicySelector());

Just FYI...the above policy selector works only for Web Host currently. If you would like to do a similar test in SelfHost, then do the following:

//NOTE: by default, the transfer mode is TransferMode.Buffered
config.TransferMode = System.ServiceModel.TransferMode.StreamedRequest;

After Update B of the post above:

public class LoggingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.Content != null)
        {
            string requestContent = await request.Content.ReadAsStringAsync();
        }

        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

        if (response.Content != null)
        {
            string responseContent = await response.Content.ReadAsStringAsync();
        }

        return response;
    }
}

I was thrown by that comment by Filip. I did use ReadAsStringAsync and my model would be null. Here's the basic code I used in the ITraceWriter implementation: request.Content.ReadAsStringAsync().ContinueWith(s => { string requestText = s.Result; Logger.Log(requestText); });

I am unable to repro the issue you are mentioning. For example (not the best way to do it), i have the following code in the WriteTrace method of SimpleTracer from Mike Wasson's sample: if (rec.Request != null){ Console.WriteLine(rec.Category + ", " + rec.Request.Content.ReadAsStringAsync().Result); }

Thanks for trying to repro. Trying to figure out what's different. I'm using MVC 4 and running in IIS Express for my local dev. Maybe IIS Express is the difference. I'm trying something different and will post back.

I tried following this: weblogs.asp.net/pglavich/archive/2012/02/26/ which like Filip's example uses a DelegatingHandler. I don't know if it is a timing issue or what, but some calls to a method from test harness that makes multiple calls seem to work and some seem to end up with a null model. Also, a side note: trying to follow Filip's very simple example directly he uses and await which means the method has an async so it forces me to return response.Result, not just response. I may need to just create a simpler example to test.

I updated the question with more details and a sample. If you have a chance and can try to repro with the sample code or offer any further insight I'd appreciate it.

ASP.NET Web API Logging Inbound Request Content - Stack Overflow

asp.net-mvc asp.net-web-api
Rectangle 27 0

Button "Select" needs to be wrapped by html FORM tag that is in MVC .cshtml view can be rendered by @Html.BeginForm() extension method (see help for it). Once you have an html form, you can make user able to post it back to web server by setting this button as of type "submit". When user pushes it, the browser gathers names and values of html elements which are inside FORM such like input or select but not label etc, turns them into key-value pairs and sends to web server via HTTP POST request to the url specified as FORM's attribute (such like http://myHost.com/Foo/Bar). Web server receives this request and parses it - both URL query string, headers and, of course, posted data. According to MVC convensions and the default routing, the http://myHost.com/Foo/Bar means all request data should be forwarded to the Bar action of the Foo controller. Inside action programemr can access the FORM's values (as well as many other request info) via HttpContext.Request.Form collection. But the another great point of .NET MVC implementation is the model binding mechanism. It tries to map incoming FORMs key-value pairs on Action parameter basing on equality of keys and parameter names (actually, it is even more complicated). Thus, if you had /select name="myDdlId"/ html tag on your page, and user selected 1st option with Id=123, and submitted form, then the incoming FORM key-value pair would be "myDdlId=123". Once you provide your Bar action with int myDdlId parameter then binder will automatically populate it with "123" as the key and the parameter names are equal. Not only parameters of simple types can be used in Action - actually, you can create your own MyModel class with MyDdlId integer property - the binder will instantiate the object and set its MyDdlId=123. Default binder is pretty smart and covers most of needs, but you can also create your own binders. Thus implicit binding greatly helps us not to think of FORMs values collections and key-value pairs, we just provide an Action with the specially designed object as parameter and - voila! - immediately have this object populated with the corresponding values. Once you have got the selected item's ID and performed query over your db, you have your entities to display for user. You need to have another view model class like MyEntitiesViewModel that can hold entities array. Once you have your very big business entities from database, you create an instance myEntitiesModel of MyEntitiesViewModel and populate it with needed entities properties. After that you write return View("~/Views/AllEntities.cshtml", myEntitiesModel); that means you're taking AllEntities.cshtml template, provide it with myEntitiesModel, render as html page and send back to client. Was this helpful?

c# - MVC controller concept - Stack Overflow

c# asp.net-mvc
Rectangle 27 0

This happens because, by design, all HTML helpers first look at the ModelState when binding and after that in the model itself. So if you intend to modify some value that was part of the POST request you will need to remove it from ModelState first if you want this change to be reflected in the view:

[HttpPost]
public ActionResult SomeAction(MyViewModel model)
{
    // We remove the Bar property that was part of the request because
    // we modify its value here
    ModelState.Remove("Bar");
    model.Bar = "Some modified value";

    return View(model);
}

This assumes that in the corresponding view you have an input field for it:

@Html.EditorFor(x => x.Bar)

Actually I'm using GET request, but your solution works very well. Thank you very much! Best regards.

asp.net mvc - View does not affect models changes - Stack Overflow

asp.net-mvc asp.net-mvc-2
Rectangle 27 0

I think that it would help if you had a better understanding of how model binding works when you post back to an action method. In most cases, it is unecessary and inefficient to pass a view model as a parameter to a POST action method. What you are doing is loading the view model into memory twice when you pass your view model as a parameter (assuming a strongly typed view). When you do a post back the model becomes part of the form collection (through model binding) in the request object in the BaseController class that every controller inherits from. All that you need to do is to extract the model from the Form collection in the Request object in the BaseController. It just so happens that there is a handy method, TryUpdateModel to help you do this. Here is how you do it

[POST]
public ActionResult Save()
{
    var saveVm = new SaveViewModel();

    // TryUpdateModel automatically populates your ViewModel!
    // TryUpdateModel also calls ModelState.IsValid and returns
    // true if your model is valid (validation attributes etc.)
    if (TryUpdateModel(saveVm)
    {
        // do some work
        int id = 1;
        var anotherSaveVm = GetSaveVmBySomeId(id);

        // do more work with saveVm and anotherSaveVm
        // clear the existing model
        ModelState.Clear();
        return View(anotherSaveVm);
    }
    // return origonal view model so that the user can correct their errors
    return View(saveVm);
}

I think that the data in the form collection contained in the request object is being returned with the view. When you pass the model back to the post action method as a parameter, I believe it is passed in the query string (see Request.QueryString). Most of the time, it is best to only pass one or two primitive type parameters or primitive reverence types such as int? to an action method. There is no need to pass the entire model as it is already contained in the Form collection of the Request object. If you wish to examine the QueryString, seee Request.QueryString.

asp.net - Why is it that when I pass a Model to my .Net MVC 4 Controll...

asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4
Rectangle 27 0

Disabled form fields are not sent back to the server by the browser in a POST request (according to HTTP standards), so the MVC framework will not have the values to do the model binding before entering your controller.

  • Avoid using disabled and mix some css and javascript to obtain the feeling of disabled for fields.
  • On form submit event make sure to enable all the fields back
  • Put some hidden fields in the form with the names from the controls, and update them every time a value changes.

c# - Why form not submitting with models in asp.net mvc 5 .(Another Mo...

c# jquery asp.net asp.net-mvc
Rectangle 27 0

This isn't about DropDownListFor method, it is about model binding. When you return another view after a POST request, ASP.NET MVC thinks that the validation has failed and uses the previous values for model binding. You can read more about this behavior in this blog post.

You can prevent this by clearing ModelState in your action.

[HttpPost]
public ActionResult SomeAction()
{
    ModelState.Clear();
    //return View(model); 
}

c# - DropDownListFor<> not using my selected value if I change it in t...

c# asp.net-mvc razor
Rectangle 27 0

You can have your post method that takes in a HttpRequestMessage to by pass the model binding logic and you can read the content of the request directly:

public HttpResponseMessage Post(HttpRequestMessage req)
    {
        var data = req.Content.ReadAsStringAsync().Result; // using .Result here for simplicity...
        ...

    }

By the way, the reason why the action that takes in JObject doesn't work is because of 'ObjectId("...")' that is used as the value of "_id" in your data...

c# - how to post arbitrary json object to webapi - Stack Overflow

c# json mongodb asp.net-web-api
Rectangle 27 0

Model binding works by binding the key/value pairs sent by the browser in a form post to model properties (or view data). A form input's name attribute is what is used as its key in the form data submitted in a POST request.

When you use HTML helpers to render form fields, the framework automatically generates the appropriate name attributes required to ensure that the field will bind properly to the property specified in the expression you pass to the helper.

If you change the name, you break the only connection between the form input and the property it binds to.

Hi @AntP, that makes a lot of sense but then I don't understand why they would provide a way to change the name as I did then, Is there a way I can change the actual names display on the HTML source without breaking up the binding mechanism?. Thanks.

That mechanism is for specifying any HTML attribute - it's not specifically for changing the name attribute. If you tell the framework you want to override the name attribute, the framework should (and does) defer to your judgment. You might well have a very good reason for doing so (in fact, in more complex binding scenarios the framework is often not quite clever enough to generate the right name itself and you have to give it a helping hand).

Why do you want to change the names in the HTML source? Posting form values under specified names is a standard HTML convention. If you just want to hide the names of the properties, just use meaningless names (and apologise to your colleagues). If that's not good enough, you'll need to delve deeper and look into custom model binding. I don't really see what this achieves, though.

I thought that exposing the properties of my model or viewmodel on the HTML source could be somewhat unsafe that's it. Plus l have this habit to put an identifier of the type of the object along with a similar name of the property on HTML objects so that's why.

You should build your web app under the assumption that anyone can put whatever values they want in your view models on a form post - because they can. As long as you account for that, there's nothing unsafe about exposing the names. The bigger issue is making sure that you don't have any view model properties that can be used maliciously.

c# - Model binding isn't working when htmlAttribute Name is changed on...

c# asp.net-mvc asp.net-mvc-4 model-binding
Rectangle 27 0

View's don't have anything to do in POST request and model binding

When you have strong type views, model type is barely used to have the simplicity of code intellisense in view's code (so you can use lambda expressions like in your example).

But when you POST data back, nothing gets checked against the view. It gets checked against controller action parameters though. And if there's a parameter with a certain custom model binder type, that particular model binder is used to process incoming data.

But to answer your question: TextBoxFor checks your strong type view's model and generates particular textbox with correct name attribute. So data from it will be posted back under the correct form field name.

To go even deeper. It's the view engine that parses view's ASPX code and runs all server side scripts including Html.TextBoxFor() call.

Asp.net mvc 2 model binders what's behind scene - Stack Overflow

asp.net asp.net-mvc asp.net-mvc-2 modelbinders