Complex models and partial views - model binding issue in ASP.NET MVC 3
Instead of:
@Html.Partial("_SimplePartial", Model.Simple)
I would recommend you using Editor templates:
@model ComplexModel
@using (Html.BeginForm())
{
@Html.EditorFor(x => x.Simple)
<input type="submit" value="Save" />
}
and then put the simple partial inside ~/Views/Shared/EditorTemplates/SimpleModel.cshtml
or inside ~/Views/Home/EditorTemplates/SimpleModel.cshtml
where Home
is the name of your controller:
@model SimpleModel
@Html.LabelFor(model => model.Status)
@Html.EditorFor(model => model.Status)
Of course if you prefer to have the partial in some special location and not follow the conventions (why would you?) you could specify the location:
@Html.EditorFor(x => x.Simple, "~/Views/SomeUnexpectedLocation/_SimplePartial.cshtml")
then everything will come into place as expected.
ASP.NET MVC 3 complex model binding issue
I think what you are looking for is the binding of collections. This may help: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
MVC Complex model binding with inheritance, nested viewModels and partial views
The problem is with using partials. Each time you go into the a partial, the model context changes, so the inputs that Razor generates for you are not taking the full property path into account. For example, if you were to do the following in your main view:
@Html.EditorFor(m => m.TrainerVM.SomeProperty)
The resulting HTML would be akin to:
<input type="text" name="TrainerVM.SomeProperty" />
However, when using a partial, your helper would be called as:
@Html.EditorFor(m => m.SomeProperty)
And the resulting HTML would be akin to:
<input type="text" name="SomeProperty" />
Once this gets posted back, the modelbinder doesn't know that SomeProperty
belongs to the TrainerVM
instance so it can't determine where to bind the posted value, and you end up with nulls. To continue to use partials but side-step this problem, you'll need to pass a value for ViewData.TemplateInfo.HtmlFieldPrefix
(which is used to properly prefix the names of all the fields in the partial):
@Html.Partial("PartialTrainer", Model.TrainerVM, new ViewDataDictionary(ViewData)
{
TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "TrainerVM" }
})
asp mvc partial view model binding
The problem is your post method [Bind(Include = "some property")]
. Which means you specified the list of properties only included in the model object, Other properties are not included in the model object.
The problem is Binding model is a complex model
The data structure you are posting in your Ajax call is not representative of what is expected in your controller, try this:
requestData = {
BrandDto : {
BrandId: params.pk,
columnName: params.name,
newValue: params.value
}
};
Losing partial view model form values
Partial views are still technically views. You're unable to get the values from the partial just because it is inside of the main view's form.
Look into Editor Templates, they'll allow you to achieve what you're looking for.
More on that here
Polymorphic model binding / Complex Models
Here is a demo:
Index.cshtml(when select SmartPhone,use example.cshtml,when select Laptop,use example1.cshtml):
@model MainCont
@{
ViewData["Title"] = "Home Page";
}
<form asp-action="create" asp-controller="home" method="post">
<select id="select" name="select">
<option value="SmartPhone">SmartPhone </option>
<option value="Laptop">Laptop </option>
</select>
<div id="sample"></div>
<button type="submit">გაგზავნა</button>
</form>
@section scripts{
<script>
$(function () {
GetPartialView();
})
$("#select").change(function () {
GetPartialView();
})
function GetPartialView() {
$.ajax({
url: "/Test1/ReturnExample",
type: "POST",
data: {
select: $("#select").val()
},
success: function (data) {
$('#sample').html(data);
},
error: function (reponse) {
alert("error : " + reponse);
}
});
}
</script>
}
example.cshtml:
@model SmartPhone
@Html.TextBoxFor(model => model.imei)
@Html.TextBoxFor(model => model.screensize)
example1.cshtml:
@model Laptop
@Html.TextBoxFor(model => model.CPU)
@Html.TextBoxFor(model => model.GPu)
Controller:
public IActionResult Index()
{
return View(new MainCont());
}
public IActionResult ReturnExample(string select)
{
if (select == "SmartPhone")
{
return PartialView("~/Views/Test1/example.cshtml", new SmartPhone());
}
else {
return PartialView("~/Views/Test1/example1.cshtml", new Laptop());
}
}
Create Action in Home Controller:
[HttpPost]
public IActionResult Create([ModelBinder(typeof(DataBinder))]MainCont mainCont) {
return Ok();
}
DataBinder:
public class DataBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model1 = new MainCont();
var select = bindingContext.ValueProvider.GetValue("select").FirstValue;
if (select == "SmartPhone")
{
var model2 = new SmartPhone();
model2.screensize = bindingContext.ValueProvider.GetValue("screensize").FirstValue;
model2.imei = bindingContext.ValueProvider.GetValue("imei").FirstValue;
model1.Device = model2;
}
else if (select == "Laptop")
{
var model2 = new Laptop();
model2.CPU = bindingContext.ValueProvider.GetValue("CPU").FirstValue;
model2.GPu = bindingContext.ValueProvider.GetValue("GPu").FirstValue;
model1.Device = model2;
}
bindingContext.Result = ModelBindingResult.Success(model1);
return Task.CompletedTask;
}
}
result:
Related Topics
Custom JSON Serialization for Each Item in Ienumerable
How to Create an Expression Tree Calling Ienumerable<Tsource>.Any(...)
Programmatically Encrypting a Config-File in .Net
How to Perform an Insert and Return Inserted Identity with Dapper
Methodinvoker VS Action for Control.Begininvoke
C# Working with Entity Framework in a Multi Threaded Server
Password Encryption/Decryption Code in .Net
How to Tell If My Application Is Running as a 32-Bit or 64-Bit Application
Convert Newtonsoft.JSON.Linq.Jarray to a List of Specific Object Type
Handling Multiple Requests with C# Httplistener
Retrieve the Respective Coordinates of All Words on the Page with Itextsharp
The Notorious Yet Unaswered Issue of Downloading a File When Windows Security Is Required
Return Content with Ihttpactionresult for Non-Ok Response
Add a Package with a Local Package File in 'Dotnet'
How to Get the Available Wifi Aps and Their Signal Strength in .Net
How to Determine a Session Variable Is Null or Empty in C#
Retrieving Files from Directory That Contains Large Amount of Files