Asp.net mvc 为表单页设置ViewData变量的最佳方法?

Asp.net mvc 为表单页设置ViewData变量的最佳方法?,asp.net-mvc,Asp.net Mvc,我想这是我们都知道的一个普遍模式。我们有一个显示表单的操作。表单将被分配到另一个操作。根据验证,我们重新重定向或显示无效表单。令人恼火的是,表单页面需要在ViewData中放置一组变量(有些可能是复杂的数据)。这迫使在两个操作中复制代码 如何解决这种重复?一个例子可以是一个动作过滤器,以确保设置了一些变量,但为每种情况定义一个新的过滤器有点过分了。。。还是初始化方法?有没有最佳实践 public ActionResult EditSettings() { // Set some vari

我想这是我们都知道的一个普遍模式。我们有一个显示表单的操作。表单将被分配到另一个操作。根据验证,我们重新重定向或显示无效表单。令人恼火的是,表单页面需要在ViewData中放置一组变量(有些可能是复杂的数据)。这迫使在两个操作中复制代码

如何解决这种重复?一个例子可以是一个动作过滤器,以确保设置了一些变量,但为每种情况定义一个新的过滤器有点过分了。。。还是初始化方法?有没有最佳实践

public ActionResult EditSettings()
{
    // Set some various variables for the view
    ViewData["timezoneinfos"] = TimeZoneInfos;
    ViewData["emailtemplates"] = Templates;

    // Fill a SettingsForm object

    return View(form);
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditSettings(SettingsForm form)
{
    if (ModelState.IsValid)
    {
        // TODO: save model

        return RedirectToRoute(....);
    }

    // Set some various variables for the view (again)
    ViewData["timezoneinfos"] = TimeZoneInfos;
    ViewData["emailtemplates"] = Templates;

    return View(form);
}

尽量避免使用任意键设置ViewData。您应该有一个ViewModel对象,其中包含显示视图所需的所有数据

public class EditSettingsViewModel {
   public IEnumerable<TimeZoneInfo> TimeZoneInfos {get;set;} 
    //then your form properties etc...
}
公共类编辑设置视图模型{
公共IEnumerable时区信息{get;set;}
//然后你的表单属性等等。。。
}
将此模型设置为视图的视图模型


一般来说,每个视图都应该有自己的ViewModel。

我以前做过一些事情,让您的
[HttpGet]
版本的操作作为参数在ViewModel中执行

[HttpGet]
public ActionResult EditSettings(SettingsForm form)
{
    // Set some various variables for the view
    ViewData["timezoneinfos"] = TimeZoneInfos;
    ViewData["emailtemplates"] = Templates;

    if( form.SomeKeyThatWouldBePopulatedOnPostBack == null )
      // Fill a SettingsForm object

    return View(form);
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditSettings(SettingsForm form)
{
    if (ModelState.IsValid)
    {
        // TODO: save model

        return RedirectToRoute(....);
    }

    return EditSettings(form);
}

在某些情况下,为了避免重复,我所做的是覆盖
OnActionExecuted
,并在那里填充
ViewData


如果您只需要为特定操作执行此操作,您可以查看
filterContext.ActionDescriptor.ActionName
,以获取执行的操作名称。

是的,这通常是我所做的,但有时我无法避免,并且/或者不想围绕另一个代码不可访问的对象编写包装器模型对象。无论如何,TimeZoneInfo不会发布回POST action…它并不总是最合适的
TimeZoneInfo
将仅为空-这无关紧要,因为您不会检查它或将其包含在验证中。我不确定我的问题是否正确。在我看来,您想用一些初始值初始化viewdatadictionary?为什么不创建一个在构造函数中执行此操作的强类型viewdata?或者创建一个GetViewData()方法来为您进行初始化。+1是的,操作过滤器是当前的顺序,哦,强类型视图模型,而不是快乐的魔术字符串。调用“HttpGet方法”毕竟是一种干净、快速的方式来重新启动表单。谢谢