Adi*_*lil 3 asp.net-mvc asp.net-ajax
的ViewModels
//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;
}
Run Code Online (Sandbox Code Playgroud)
这是视图
//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>
}
Run Code Online (Sandbox Code Playgroud)
这是AJAX Call
<script>
function ddSelectionChanged(element){
$('#services').load('@(Url.Action("GetServices"))?serviceType =' element.value);
};
</script>
Run Code Online (Sandbox Code Playgroud)
这是控制器
//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);
}
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,部分View按预期呈现,但是当我发布索引时,MainViewModel的属性"Services"返回"null".问题是模型的"服务"属性不会重新绑定到MainViewModel,因为它会动态呈现为部分视图.
如何在部分视图渲染时或在发布表单之前重新绑定模型?
发布到操作时,模型绑定器填充的唯一部分是已发布的字段和数据.如果您丢失了服务,则需要在表单中提供字段以在帖子中保留该数据.
例如,在您的AJAX返回的任何HTML中,您需要为每个属性包含类似隐藏输入的内容Service:
@Html.HiddenFor(m => m.ServiceID)
@Html.HiddenFor(m => m.ServiceName)
Run Code Online (Sandbox Code Playgroud)
然后,当您的表单发布时,该数据将与其他所有内容一起发布,并且模型绑定器将能够Services恰当地填充您的列表.但是,您还需要注意生成的字段名称.特别是如果响应AJAX请求的动作返回的部分视图使用的是List<Service>直接代替的模型MainViewModel,那么渲染的HTML将失去知道它应该绑定到被调用属性的上下文Services.换句话说,在您的HTML中,您的字段名称将最终变为类似[0].ServiceID而不是Services[0].ServiceID.后者对于使模型绑定器正确处理发布的数据是必要的.
您可以通过将自定义传递ViewDataDictionary给您Html.Partial或您的Html.RenderPartial电话来弥补这一点.通过定义一个新的TemplateInfo与HtmlFieldPrefix设置为任何它需要的,即:
@Html.Partial("_SomePartial", someModel, new ViewDataDictionary
{
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "SomePrefix" }
}
Run Code Online (Sandbox Code Playgroud)
但是,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);
}
Run Code Online (Sandbox Code Playgroud)
另外值得一提的是,如果您以前没有使用过绑定集合,那么您需要使用for循环而不是foreach循环来为字段名称提供适当的上下文.例如,类似以下内容:
@foreach (var service in Model)
{
@Html.HiddenFor(m => service.ServiceID)
}
Run Code Online (Sandbox Code Playgroud)
会产生一个名称为的字段service.ServiceID.模型绑定器不知道这个值应该去哪里,基本上会忽略它.相反,你需要做:
@for (var i = 0; i < Model.Count(); i++)
{
@Html.HiddenFor(m => m[i].ServiceID)
}
Run Code Online (Sandbox Code Playgroud)
这会让你的字段像名字一样[0].ServiceID.同样,前缀是一个问题,因此您需要两个组件才能使其正常工作.
| 归档时间: |
|
| 查看次数: |
2689 次 |
| 最近记录: |