ASP.NET MVC4 Model Not Binding - asp.net-mvc-4

I have a very simple ASP.NET MVC4 page. It's rendering an edit form for the CustomerModel. The form displays correctly, but when I hit edit and post back, the model isn't being bound. Instead, all the properties of the CustomerModel are left at their defaults. Note that the correct controller method is being invoked, so that's not the issue.
I can see the form values with matching names to the model properties (Id, Name, Description), but the model doesn't have them set.
Ideas?
Here is the model:
public class CustomerModel
{
[Required]
public Guid Id;
[Required]
public string Name;
[Required]
public string Description;
}
And here is the relevant controller method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomerModel customerModel)
{
if (ModelState.IsValid)
{
//...Do stuff
return RedirectToAction("Index");
}
return View(customerModel);
}
Finally, here is a screen shot of the form collection with the populated values:

Your model has public fields but not public properties, these are not the same.
Change to:
public class CustomerModel
{
[Required]
public Guid Id {get; set;}
[Required]
public string Name {get; set;}
[Required]
public string Description {get; set;}
}
The default MVC model binder will work with properties, not fields.
More about this here - http://rightbrainleft.net/2011/02/default-mvc-model-binder-doesnt-like-fields/

Related

How to pass FormFile and json object in single model using Asp.net core

I have a model class. That class contains multiple properties , list of custom class and list of formfile data. I need to create post request for this model using Asp.net Core.
Model Class
public class TenoModel
{
[Key]
public int Id { get; set; }
public DateTime Date { get; set; }
public float Salary { get; set; }
[Required]
public string User { get; set; }
public List<IformFile> files {get;set;}
public List<Employee> employees{get;set;}
}
Custom class for employee
public class Employee
{
public int Id {get;set;}
public string Name {get;set;}
public double Salary {get;set;}
}
HttpPost request:
[HttpPost("CreateTeno")]
[Consumes('multipart/form-data']
public async Task<IActionResult> CreateTeno([FormFile] TenoModel model)
{
..... save the model data to teno database
}
When I execute the HttpPost request on swagger Formfile data and some property data come to incoming request on CreateTeno method. I fill the Employee object also in swagger. but that data not coming in my CreateTeno method. List of Employee data count zero. How to pass model class with multiple properties, List of IformFile and multiple list customclass in HTTP post request. Give a sample example.
You'll have to change the signature of your controller method like this:
public async Task<IActionResult> CreateTeno([FromForm] TenoModel model)
Tested with Postman like this
Please note that you have a syntax error here: [Consumes('multipart/form-data'], should be [Consumes("multipart/form-data")]

Custom validation fires if in model class but not on page property

I have a contact Razor page implemented in ASP.NET Core 2.0. I am using model binding and custom validation.
If I use custom validation on a separate model class, the validation method is called. If I use custom validation on a property on the PageModel, the validation method is not called. However, all properties are successfully bound.
Here's the PageModel class and the separate model class:
public class ContactModel : PageModel
{
[BindProperty]
public ContactMessageModel ContactMessageModel { get; set; }
[BindProperty, CustomValidation]
public string SomeData { get; set; }
public IActionResult OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
return RedirectToPage("MessageSent");
}
}
public class ContactMessageModel
{
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required, CustomValidation]
public string Message { get; set; }
}
A test validation attribute class is as follows:
public class CustomValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
return ValidationResult.Success;
}
}
The validation attribute is called for the ContactMessageModel.Message property, but it isn't called for ContactModel.SomeData property.
Why is this and how do I fix it?
I was running into this too. In my case my issue was because I missed the addition of the [BindProperty] attribute when I moved the properties from a wrapper class model into the PageModel directly. I see that's not the case for you.
In your case I do see that you have the [Required] attribute on all properties except the ContactModel.SomeData. Maybe adding [Required] there would get things acting as you would expect?

Mapping nested x-form-urlencoded data to DTO in Asp.NET Core

Implementing a webhook in Asp.Net Core which is POSTed to with application/x-form-urlencoded data - it's receiving data in a format that is designed to be easily processable in PHP w/ the $_POST variable (nested associative array) - the form fields look like
foo
bar[barf]
baz[bat][bark]
baz[bat][bant]
Is there a nice (elegant and little code required) way to wire up the Asp.NET Core model binding to handle the nested structure here? i.e. when the webhook gets POSTed to, we parse a C# POCO -
something like
class RootDto {
public string Foo {get; set;}
public Bar Bar {get; set;}
public Baz Baz {get; set;}
public class Bar {
public string Barf {get; set;}
}
public class Baz {
public Bat Bat {get; set;}
public class Bat {
public string Bark {get; set;}
public string Bant {get; set;}
}
}
}
The POST body looks something like the following:
foo=somevalue&bar%5Bbarf%5D=anothervalue&baz%5Bbat%5D%5Bbark%5D=123.0&baz%5Bbat%5D%5Bbant%5D=5000
i.e.
foo=somevalue&bar[barf]=anothervalue&baz[bat][bark]=123.0&baz[bat][bant]=5000
Also, what's the low-friction way to set up a type-converter for one of these fields (e.g. assume the field "Foo" comes in as a string but we want to parse it into a struct)?
Note that I don't have control of the shape or encoding of the data coming in from the webhook (e.g. I can't request they just send me JSON).
Request body
Content-Type: application/x-www-form-urlencoded
foo=somevalue&bar%5Bbarf%5D=anothervalue&baz%5Bbat%5D%5Bbark%5D=123.0&baz%5Bbat%5D%5Bbant%5D=5000
It just works.... I have plain .net core project and controller looks like
public IActionResult Post([FromForm] RootDto request)
{
return Ok(request);
}
Btw your root class seems to be wrong I've changed to make it work
public class RootDto {
public string Foo {get; set;}
public BarClass Bar {get; set;}
public BazClass Baz {get; set;}
public class BarClass {
public string Barf {get; set;}
}
public class BazClass {
public BatClass Bat {get; set;}
public class BatClass {
public string Bark {get; set;}
public string Bant {get; set;}
}
}
}

how to make httppost actionresult bind to only part of the viewModel

I have the following sudo-code
class viewModel
{
public ICollection<modelA> parentModel
public modelC formModel
}
class modelA
{
public int ID {get;set;}
public virtual Icollection<modelB> {get;set;}
}
class modelB
{
public int ID {get;set;}
public string SomeString {get;set;}
public virtual modelA ModelA {get;set;}
}
class modelC
{
public int ModelAID {get;set;}
public string SomeString {get;set;}
}
So. the view model contains a collection of As. Each A contains a collection of Bs and there is a separate model for posting back as a form: the form will be repeated on the page, once in each instance of A with the A.ID passed in to ModelAID as a hidden field. Only one form posting is allowed on the page, The id of the form fields are formModel.ModelAID and .formModel.SomeString as they are derived from the non-parent element of the viewModel.
How do I get the ActionResult to bind only to formModel?
[HttpPost]
Public ActionResult Input(formModel vm)
{
... by default the view model being passed back is full VM, I only want the formModel so the post signature does not match
}
You can try something like
public ActionResult Input([Bind(Prefix = "formModel ")]modelC model)
{
}

How do I preseve an object type member inside an ASP.Net MVC view?

Here are my two classes:
class Company
{
public int ID{ get; set; }
public string CompanyName{ get; set; }
}
public class Division
{
public int ID{ get; set; }
public string DivisionName{ get; set; }
public virtual Company Company { get; set; }
}
I have a strongly typed EDIT view for Division, with an EditorFor for DivisionName and a HiddenFor for ID.
The problem I have is when I hit save, the Controller action gets the Division object with an NULL for Company property. When the model is not valid, and the View is returned with that object, I can no longer extract the company name in the view using #Model.Company.CompanyName.
How can I fix this?
If you don't include Company data in your view (as input fields), then nothing about Company will be posted back.
If Company is just for "display only", then re-populate it in your controller during the post before your model is returned in the view.
public ActionResult MyAction(Division model)
{
// ...
// Repopulate Company
model.Company = new Company() { ... };
return View(model);
}