Asp.net mvc 通过AJAX加载后,部分视图的ViewModel未绑定到主ViewModel的ViewModel
视图模型Asp.net mvc 通过AJAX加载后,部分视图的ViewModel未绑定到主ViewModel的ViewModel,asp.net-mvc,asp.net-ajax,Asp.net Mvc,Asp.net Ajax,视图模型 //MainViewModel public class MainViewModel { public string UserID { get; set; } public string ServiceType { get; set; } public List<Service> Services {get; set;} } public class Service {
//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;
}
这很好,局部视图按预期呈现,但当我发布索引时,MainViewModel的属性“Services”返回“null”。问题在于,模型的“服务”属性没有重新绑定到MainViewModel,因为它动态地呈现为局部视图
如何在部分视图渲染时或发布表单之前重新绑定模型?发布到动作时,modelbinder仅填充已发布的字段和数据。如果您正在丢失服务,那么您需要在表单中提供字段,以便在发布期间保留该数据 例如,在AJAX返回的任何HTML中,您都需要为
服务上的每个属性包含类似于隐藏输入的内容:
@Html.HiddenFor(m => m.ServiceID)
@Html.HiddenFor(m => m.ServiceName)
然后,当您的表单发布时,这些数据将与其他所有内容一起发布,modelbinder将能够适当地填写您的服务
列表。但是,您还需要注意生成的字段名。特别是,如果响应AJAX请求的操作返回的部分视图直接使用了类似于List
的模型,而不是MainViewModel
,则呈现的HTML将失去知道它应该绑定到名为Services
的属性的上下文。换句话说,在HTML中,字段名将以类似于[0].ServiceID
的形式结束,而不是服务[0].ServiceID
。后者对于让modelbinder正确处理发布的数据是必要的
您可以通过将自定义的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);
}
同样值得一提的是,如果您以前没有使用过绑定集合,则需要使用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)
}
for(var i=0;im[i].ServiceID)
}
这将得到名为
[0].ServiceID
的字段。同样,前缀是一个问题,因此您需要两个组件才能使其正常工作。嘿,克里斯,谢谢你。你救了我几个小时。ViewData.TemplateInfo.HtmlFieldPrefix=“Services”这解决了问题。干杯,我欠你人情。嗨,我有一个类似的问题,即使是通过在浏览器中向表中添加新行来正确呈现局部视图,但在表单发布时,父模型列表对象的项目数始终为0。它永远不会来inside@for(var i=0;ipublic PartialViewResult GetServices(string serviceType)
{
ViewData.TemplateInfo.HtmlFieldPrefix = "Services";
//Service servicesViewModel = Fetch Services from DB
return PartialView("PartialViews/Shared/_Services", servicesViewModel);
}
@foreach (var service in Model)
{
@Html.HiddenFor(m => service.ServiceID)
}
@for (var i = 0; i < Model.Count(); i++)
{
@Html.HiddenFor(m => m[i].ServiceID)
}