问题描述:

I have one scenario in my project like below.

Create Person with two views. One is parent view contains person names and the other is partial view contains address information.

if i click on submit button in parent view, i need to read the data entered in address partial view and pass it to PersonViewModel object for POST action method.

I am unable to AddressViewModel from POST Action method, getting null value. Anyone help me how to resolve this issue.

Thanks in advance.

Please find the sample code below.

ViewModels:

 public class PersonViewModel

{

public string FirstName{get;set;}

public string LastName{get;set;}

public AddressViewModel Address{get;set;}

}

public class AddressViewModel

{

public class Address1{get;set;}

public class Address2{get;set;}

}

PersonController

 public ActionResult POST(PersonViewModel model)

{

Person person=new Person();

person.FirstName=model.FirstName;

person.LastName=model.LastName;

if(model.Address!=null)

{

person.Address1=model.Address.Address1;

}

return View("Confirmation");

}

AddressController:

public ActionResult Address()

{

return View();

}

Person View:

@model POC.ViewModels.PersonViewModel

@using (Html.BeginForm())

{

@Html.AntiForgeryToken()

<div class="form-horizontal">

@Html.ValidationSummary(true, "", new { @class = "text-danger" })

<div class="form-group">

@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })

@Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })

</div>

</div>

<div class="form-group">

@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

@Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })

@Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })

</div>

</div>

<div>

@{Html.RenderPartial("~/Views/Shared/_Address.cshtml");}

</div>

<div class="form-group">

<div class="col-md-offset-2 col-md-10">

<input type="submit" value="Create" class="btn btn-default" />

</div>

</div>

</div>

}

Address Partial View:

@model POC.ViewModels.AddressViewModel

<div class="form-horizontal">

<div class="form-group">

@Html.LabelFor(model => model.Address1, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

@Html.EditorFor(model => model.Address1, new { htmlAttributes = new { @class = "form-control" } })

@Html.ValidationMessageFor(model => model.Address1, "", new { @class = "text-danger" })

</div>

</div>

<div class="form-group">

@Html.LabelFor(model => model.Address2, htmlAttributes: new { @class = "control-label col-md-2" })

<div class="col-md-10">

@Html.EditorFor(model => model.Address2, new { htmlAttributes = new { @class = "form-control" } })

@Html.ValidationMessageFor(model => model.Address2, "", new { @class = "text-danger" })

</div>

</div>

</div>

网友答案:

You partial is generating controls with name="Address1" and name="Address2" but your model does not include a property with the names Address1 and Address2 (only a property named Address which is a complex object containing properties Address1 and Address2. In order to bind to your model the name attributes would need to be name="Address.Address1" and name="Address.Address2".

The best way to solve this is to make your partial an EditorTemplate by renaming it to AddressViewModel.cshtml and placing it in the Views\Shared\EditorTemplates folder (or in the Views\YourControllerName\EditorTemplates folder, and then in the main view use

@Html.EditorFor(m => m.Address)

An alternative using a partial is to pass the prefix to the partial using addititional ViewData

@Html.Partial("Address", Model.Address, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "Address" }})

This answer also includes an example of a html helper extension method that makes adding the prefix a little easier

网友答案:

You need a form inside the view. Something like this:

@using (Html.BeginForm("POST")){
  @Html.EditorFor(m => m.FirstName)
  @Html.EditorFor(m => m.Address.Address1)
  <input type="submit"/>  
}

It is the act of submitting the form that creates the request. It is also important that you use either the helpers to create the input fields, or if you want to create them yourself, you create them with the correct names, e.g.:

<input type="text" name="Address.Address1"/>

Note the value of the name attribute, this is the value that the EditorFor will generate. This name is important so that the model binder will set the Address1 value in PersonViewModel.Address.Address1

If you render the Address with a partial view you'll have to make sure that the inputs have the correct names set. This is not a very good idea though because for all this to work the AddressViewModel property name in PersonViewModel must be Address, if you change its name to, for example MyAddress, you need to update the input's names to MyAddress.Address1, etc.

相关阅读:
Top