View 模型
//MainViewModel
public class MainViewModel
{
public string UserID { get; set; }
public string ServiceType { get; set; }
public List<Service> Services {get; set;}
}
public class Service
{
public string ServiceID {get; set;}
public string ServiceName {get; set;
}
这是 View
//Index.cshtml
@model ParentViewModel
@{
<div>
@Html.DropDownListFor(model => model.UserID, new{onchange="ddSelectionChanged(this)"})
<div id="services">
//This is filled with the ajax
</div>
</div>
}
这是 AJAX 调用
<script>
function ddSelectionChanged(element){
$('#services').load('@(Url.Action("GetServices"))?serviceType =' element.value);
};
</script>
这是 Controller
//Controller
public class UserServicesController : Controller
{
public ActionResult Index()
{
return View();
}
public PartialViewResult GetServices(string serviceType)
{
//Service servicesViewModel = Fetch Services from DB
return PartialView("PartialViews/Shared/_Services", servicesViewModel);
}
}
这工作正常,部分 View 按预期呈现,但是当我发布索引时,MainViewModel 的属性“服务”返回“空”。问题是模型的“服务”属性没有重新绑定(bind)到 MainViewModel,因为它动态呈现为局部 View 。
如何在局部 View 渲染时或发布表单之前重新绑定(bind)模型?
最佳答案
当您发布到操作时,modelbinder 填充的唯一部分是发布的字段和数据。如果您失去了服务,那么您需要在表单中提供字段以在发布期间保留该数据。
例如,在您的 AJAX 返回的任何 HTML 中,您需要为 Service
上的每个属性包含隐藏输入之类的内容。 :
@Html.HiddenFor(m => m.ServiceID)
@Html.HiddenFor(m => m.ServiceName)
然后,当您的表单发布时,该数据将与其他所有内容一起发布,并且模型绑定(bind)器将能够填写您的
Services
。适当列出。但是,您还需要注意生成的字段名称。特别是如果您的响应 AJAX 请求的操作返回的部分 View 使用像 List<Service>
这样的模型直接代替MainViewModel
, 那么渲染的 HTML 将失去知道它应该绑定(bind)到一个名为 Services
的属性的上下文。 .换句话说,在您的 HTML 中,您的字段名称最终将类似于 [0].ServiceID
而不是 Services[0].ServiceID
.后者对于让模型绑定(bind)器正确处理发布的数据是必要的。您可以通过传递自定义
ViewDataDictionary
来弥补这一点。给您的Html.Partial
或 Html.RenderPartial
来电。通过定义一个新的 TemplateInfo
与 HtmlFieldPrefix
设置为所需的任何值,即:@Html.Partial("_SomePartial", someModel, new ViewDataDictionary
{
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "SomePrefix" }
}
但是,返回
PartialView
时会比较棘手。直接,因为 PartialView
不接受自定义参数 ViewDataDictionary
.我自己没试过,但是可以设置HtmlFieldPrefix
直接在您的操作中:public PartialViewResult GetServices(string serviceType)
{
ViewData.TemplateInfo.HtmlFieldPrefix = "Services";
//Service servicesViewModel = Fetch Services from DB
return PartialView("PartialViews/Shared/_Services", servicesViewModel);
}
另外值得一提的是,如果您以前没有使用过绑定(bind)集合,那么您需要使用
for
循环而不是 foreach
循环以便为字段名称提供适当的上下文。例如,如下所示:@foreach (var service in Model)
{
@Html.HiddenFor(m => service.ServiceID)
}
将产生一个名称为
service.ServiceID
的字段. modelbinder 不知道这个值应该去哪里并且基本上会忽略它。相反,您需要执行以下操作:@for (var i = 0; i < Model.Count(); i++)
{
@Html.HiddenFor(m => m[i].ServiceID)
}
这会让你的字段名称像
[0].ServiceID
.同样,前缀是一个问题,因此您需要两个组件才能使其正常工作。
关于asp.net-mvc - 通过 AJAX 加载后,部分 View 的 View 模型未绑定(bind)到主视图模型的 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26980907/