我们这里将要谈到的是ASP.NET MVC PRG数据验证,主要是参考一些国外关于PRG数据验证的文章,希望对大家有所帮助。

我的理念:

既然是ASP.NET MVC,那就肯定要用PRG。但是简单的PRG不能在输入页面显示Html.ValidationMessage,另一个就是之前的数据会被全部清空或者初始化了。

想想要我是打了半天的字一下全没了那多惨啊。你的访客不气傻了才怪。

OK,Google一下,找到了http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx

阿,他叫什么名字我不认识,我也看不懂英文的版权声明,所以这只有个链接没署名了。谁认识他叫他写个C#版或者VB.NET版的版权声明吧,谢谢。

英文不好不要紧,直接看第13点:Use PRG Pattern for Data Modification 

  1.     Controller    
  2.     [AcceptVerbs(HttpVerbs.Get), OutputCache(CacheProfile = "Dashboard"), StoryListFilter, ImportModelStateFromTempData]    
  3.     public ActionResult Dashboard(string userName, StoryListTab tab, OrderBy orderBy, int? page)    
  4.     {    
  5.         //Other Codes    
  6.         return View();    
  7.     }    
  8.        
  9.     [AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]    
  10.     public ActionResult Submit(string userName, string url)    
  11.     {    
  12.         if (ValidateSubmit(url))    
  13.         {    
  14.             try   
  15.             {    
  16.                 _storyService.Submit(userName, url);    
  17.             }    
  18.             catch (Exception e)    
  19.             {    
  20.                 ModelState.AddModelError(ModelStateException, e);    
  21.             }    
  22.         }    
  23.        
  24.         return Redirect(Url.Dashboard());    
  25.     }   

自定义了两个ActionFilter,阿,作者好像打错别字了。您别在意。


  1.     ModelStateTempDataTransfer    
  2.     public abstract class ModelStateTempDataTransfer : ActionFilterAttribute    
  3.     {    
  4.         protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName;    
  5.     }    
  6.        
  7.     public class ExportModelStateToTempData : ModelStateTempDataTransfer    
  8.     {    
  9.         public override void OnActionExecuted(ActionExecutedContext filterContext)    
  10.         {    
  11.             //Only export when ModelState is not valid    
  12.             if (!filterContext.Controller.ViewData.ModelState.IsValid)    
  13.             {    
  14.                 //Export if we are redirecting    
  15.                 if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))    
  16.                 {    
  17.                     filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;    
  18.                 }    
  19.             }    
  20.        
  21.             base.OnActionExecuted(filterContext);    
  22.         }    
  23.     }    
  24.        
  25.     public class ImportModelStateFromTempData : ModelStateTempDataTransfer    
  26.     {    
  27.         public override void OnActionExecuted(ActionExecutedContext filterContext)    
  28.         {    
  29.             ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;    
  30.        
  31.             if (modelState != null)    
  32.             {    
  33.                 //Only Import if we are viewing    
  34.                 if (filterContext.Result is ViewResult)    
  35.                 {    
  36.                     filterContext.Controller.ViewData.ModelState.Merge(modelState);    
  37.                 }    
  38.                 else    
  39.                 {    
  40.                     //Otherwise remove it.    
  41.                     filterContext.Controller.TempData.Remove(Key);    
  42.                 }    
  43.             }    
  44.        
  45.             base.OnActionExecuted(filterContext);    
  46.         }    
  47.     }   

因为我用的是VB.NET,直接拿工具转了放自己项目里,英文不懂照他的源代码套上去一试。



哈,成功了,可爱的Html.ValidationMessage来了。



但是还是没有解决数据被清空或初始化的问题。



这下惨了,Google也好,百度也好,还是在博客园里找这找那都没找着。我估计可能我找的方法不对吧,不然这么多人都碰到的问题怎么没人发出来呢。



最后在园子的小组里找到http://space.cnblogs.com/group/topic/7919/ 第三个回复有说ModelState.SetModelvalue方法,拿过来一试,真不错。



所以修改了一下刚才所说的两个ActionFilter中的ExportModelStateToTempData;代码如下:


  1.     Code    
  2.         Public Overrides Sub OnActionExecuted(ByVal pFilterContext As ActionExecutedContext)    
  3.             If Not pFilterContext.Controller.ViewData.ModelState.IsValid Then    
  4.                 If TypeOf (pFilterContext.Result) Is RedirectResult OrElse TypeOf (pFilterContext.Result) Is RedirectToRouteResult Then    
  5.                     If pFilterContext.HttpContext.Request.Form.Count > 0 Then    
  6.                         Dim tFormCollection As New FormCollection(pFilterContext.HttpContext.Request.Form)    
  7.                         For Each fKey As String In tFormCollection    
  8.                             pFilterContext.Controller.ViewData.ModelState.SetModelvalue(fKey, tFormCollection.TovalueProvider(fKey))    
  9.                         Next    
  10.                         pFilterContext.Controller.TempData(mKey) = pFilterContext.Controller.ViewData.ModelState    
  11.                     End If    
  12.                 End If    
  13.             End If    
  14.             MyBase.OnActionExecuted(pFilterContext)    
  15.         End Sub   


最后说下,因为我用的VB.Net是不区分大小写的,所以我的每个参数都用p开头,临时变量用t开头,内部循环用f开头,客官将就着看吧。

本文转载于 http://www.itjianghu.net/viewlistindexallnew.asp?curpage=51