asp.net-mvc – MVC 3.0编辑可变长度列表并使用PRG模式
我创建了一个带有可变长度列表的视图,如下所述:
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/.
我正在尝试使用带有动作过滤器的PRG模式,如第13点所述:http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx. 我有一个编辑动作: [HttpGet,ImportModelStateFromTempData] public ActionResult Edit(int id) { } 和后期行动: [HttpPost,ExportModelStateToTempData] public ActionResult Edit(int id,FormCollection formCollection) { if (!TryUpdateModel<CategoryEntity>(category,formCollection)) { return RedirectToAction("Edit",new { id = id }); } // succes,no problem processing this... return RedirectToAction("Edit",new { id = id }); } 一切正常,包括验证和错误消息. 我唯一的问题是重定向后不保留新添加的项目和删除的项目(客户端删除/添加).我试图找到一种方法来重新定位新项目后更新我的模型.我更改了ImportModelStateFromTempData属性以使用OnActionExecuting覆盖而不是OnActionExecuted覆盖来使操作中的ModelState可用但我没有看到从传入的ModelState更新我的模型的干净方法. 更改了ImportModelStateFromTempData: public class ImportModelStateFromTempData : ModelStateTempDataTransfer { public override void OnActionExecuting(ActionExecutingContext filterContext) { ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary; if (modelState != null) { filterContext.Controller.ViewData.ModelState.Merge(modelState); } base.OnActionExecuting(filterContext); } public override void OnActionExecuted(ActionExecutedContext filterContext) { //ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary; //if (modelState != null) //{ // //Only Import if we are viewing // if (filterContext.Result is ViewResult) // { // filterContext.Controller.ViewData.ModelState.Merge(modelState); // } // else // { // //Otherwise remove it. // filterContext.Controller.TempData.Remove(Key); // } //} base.OnActionExecuted(filterContext); } } 对此有任何意见,非常感谢,谢谢. Harmen 更新:我想我可能会添加更多我的(伪)代码以使其更清晰: public class CategoryEntity { public int Id; public string Name; public IEnumerable<CategoryLocEntity> Localized; } public class CategoryLocEntity { public int CategoryId; public int LanguageId; public string LanguageName; public string Name; } 我的编辑视图: @model CategoryEntity @{ ViewBag.Title = Views.Category.Edit; } <h2>@Views.Category.Edit</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> <script type="text/javascript"><!-- $(document).ready(function () { $('#addItem').click(function () { var languageId = $('#languageId').val(); var index = $('#editor-rows').children().size() - 1; $.ajax({ url: this.href + '?languageId=' + languageId + '&index=' + index,cache: false,error: function (xhr,status,error) { alert(error); },success: function (html) { $('#editor-rows').append(html); } }); return false; }); $("a.removeItem").live("click",function () { $(this).parents("div.editor-row:first").remove(); return false; }); }); --></script> @using (Html.BeginForm()) { @Html.ValidationSummary(false) <fieldset> <legend>@Views.Shared.Category</legend> @Html.HiddenFor(model => model.Id) <div id="editor-rows"> <div class="editor-row"> <div class="editor-label"> @Html.LabelFor(model => model.Name,Views.Shared.NameEnglish) </div> <div class="editor-field"> @Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name) </div> </div> @for (int i = 0; i < Model.Localized.Count; i++) { @Html.EditorFor(m => m.Localized[i],"_CategoryLoc",null,null) } </div> <div class="editor-label"></div> <div class="editor-field"> @Html.DropDownList("languageId",(IEnumerable<SelectListItem>)ViewBag.LanguageSelectList) @Html.ActionLink(Views.Category.AddNewLanguage,"AddNewLanguage",new { id = "addItem" }) </div> <p class="clear"> <input type="submit" value="@Views.Shared.Save" /> </p> </fieldset> } <div> @Html.ActionLink(Views.Shared.BackToList,"Index") </div> CategoryLocEntity的编辑器模板: @model CategoryLocEntity <div class="editor-row"> @Html.HiddenFor(model => model.Id) @Html.HiddenFor(model => model.LanguageId) <div class="editor-label"> @Html.LabelFor(model => model.LanguageName,Model.LanguageName) </div> <div class="editor-field"> @Html.EditorFor(model => model.Name) <a href="#" class="removeItem">@Views.Shared.Remove</a> @Html.ValidationMessageFor(model => model.Name) </div> </div> 解决方法
我找到了一个解决方案(可能不是最优雅的解决方案,但它对我有用).我创建了自己的ModelStateValueProvider以与UpdateModel一起使用.代码基于DictionaryValueProvider.见
http://www.java2s.com/Open-Source/CSharp/2.6.4-mono-.net-core/System.Web/System/Web/Mvc/DictionaryValueProvider%601.cs.htm.
public class ModelStateValueProvider : IValueProvider { HashSet<string> prefixes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); ModelStateDictionary modelStateDictionary; public ModelStateValueProvider(ModelStateDictionary modelStateDictionary) { if (modelStateDictionary == null) throw new ArgumentNullException("modelStateDictionary"); this.modelStateDictionary = modelStateDictionary; FindPrefixes(); } private void FindPrefixes() { if (modelStateDictionary.Count > 0) prefixes.Add(string.Empty); foreach (var modelState in modelStateDictionary) prefixes.UnionWith(GetPrefixes(modelState.Key)); } public bool ContainsPrefix(string prefix) { if (prefix == null) { throw new ArgumentNullException("prefix"); } return prefixes.Contains(prefix); } public ValueProviderResult GetValue(string key) { if (key == null) throw new ArgumentNullException("key"); return modelStateDictionary.ContainsKey(key) ? modelStateDictionary[key].Value : null; } static IEnumerable<string> GetPrefixes(string key) { yield return key; for (int i = key.Length - 1; i >= 0; i--) { switch (key[i]) { case '.': case '[': yield return key.Substring(0,i); break; } } } } public class ModelStateValueProviderFactory : ValueProviderFactory { public override IValueProvider GetValueProvider(ControllerContext controllerContext) { return new ModelStateValueProvider(controllerContext.Controller.ViewData.ModelState); } } 我在de Edit(Get)动作中使用它,如: [HttpGet,ImportModelStateFromTempData] public ActionResult Edit(int id) { var category = new CategoryEntity(id); if (!ModelState.IsValid) { TryUpdateModel<CategoryEntity>(category,new ModelStateValueProviderFactory().GetValueProvider(ControllerContext)); } return View(category); } 期待您的评论…… (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 为什么知道Asp.net的生命周期对Asp.net中的编码很重要?
- .net – 在VS 2010中调试时修改代码
- asp.net-ajax – 如何在ASP.NET AJAX中实现文件下载
- asp.net – 如何让Google不会将自定义404错误页面编入索引?
- asp.net – 将linq连接到sql datacontext到业务层中的httpc
- asp.net-mvc-3 – 使用多个Web应用程序共享控制器和视图
- Asp.net Webservice – 使用jquery AJAX安全地调用webservi
- asp.net – visual studio调试错误无法启动程序没有更多文件
- asp.net – Web.HttpContext.Current.User.Identity.Name来
- asp.net-mvc-routing – 在.NET MVC 4.0 URL结构中强制使用
- asp.net – 在asp:超链接中分配声明值的问题 错
- asp.net – Handles子句需要在包含类型或其基类型
- asp.net – 后面的代码无法识别Web控件
- asp.net-web-api – Web API和.NET 4.5:声明和权
- 在ASP.NET MVC4项目中包含jquery的正确方法
- asp.net-mvc – AppDomain.GetAssemblies和Build
- asp.net – dropdownlist在页面重新加载时不会重
- asp.net-mvc-4 – .NET 4.5中没有调用HttpModule
- ASP.NET获取当前用户名
- asp.net – Moq Parent没有默认构造函数.必须显式