【问题标题】:How to redirect a POST request to a url maintaining model values in MVC如何将 POST 请求重定向到在 MVC 中维护模型值的 url
【发布时间】:2011-10-12 21:22:33
【问题描述】:

我有一个相当标准的排序/过滤/页面搜索表单,但需要控制 url 的格式。 sort/filter/page 参数都应该是 url 的一部分,例如,地址可以通过电子邮件发送给某人。

当添加另一个过滤器参数时,会发出一个 POST 请求。我的控制器方法如下所示:

[HttpPost]
public ActionResult Search(string filterField,
                           Operator filterOperator, 
                           string filterValue, 
                           PeopleGroupSearchModel model);

PeopleGroupSearchModel 由查询字符串参数填充。 filter* 参数来自已发布的表单值。

我想解析提供的过滤器值,然后将过滤器添加到模型中名为Filters 的集合中。然后,获取更新后的模型并将其转换为适当的 url,并将其作为响应传递给用户。

因此,例如,如果他们在此页面上:

PeopleGroup/Search?page=4&sort=Country

... 和 POST:

  • filterField = PeopleGroupName
  • filterOperator = 等于
  • filterValue = 祖鲁语

...一旦所有处理完成,他们浏览器中的地址应该是这样的:

PeopleGroup/Search?page=4&sort=Country&PeopleGroupName=Zulu&PeopleGroupName_op=Equals

所以,或多或少我想做的是:

[HttpGet]
public ActionResult Search(PeopleGroupSearchModel model)
{
    PeopleGroupData.Search(model);
    ViewData.Model = model;
    return View();
}

[HttpPost]
public ActionResult Search(string filterField,
                           Operator filterOperator,
                           string filterValue,
                           PeopleGroupSearchModel model)
{
    PeopleGroupFilter filter = ParseFilter(filterField, 
                                           filterOperator, 
                                           filterValue);
    model.Filters.Add(filter);
    return RedirectToAction("Search", ???);
}

我是非常 MVC 新手,所以如果我完全错误地处理这个问题,请告诉我!

【问题讨论】:

    标签: asp.net-mvc model-view-controller asp.net-mvc-2


    【解决方案1】:

    在 ASP.NET MVC 中实现 Redirect-After-Post 模式(这是您所追求的,恕我直言,这是一个非常好的模式)有多种可能性:

    1. 使用TempData。在 POST 操作中,将模型存储在 TempData 中并重定向:

      TempData["model"] = model;
      return RedirectToAction("Search");
      

      然后在 Search 操作中检查 TempData 是否存在以获取模型:

      PeopleGroupSearchModel model = TempData["model"] as PeopleGroupSearchModel;
      

      这种方法的缺点是TempData 仅针对单个重定向保留,这意味着如果用户在执行 Search GET 操作时按 F5,您就完蛋了。这可以通过使用 Session 来缓解。但是当然 Session 引入了另一个可伸缩性问题。所以我不喜欢这种方法。

    2. 传递请求的所有属性:

      return RedirectToAction("Search", new {
          prop1 = model.Prop1,
          prop2 = model.Prop2, 
          ....
      });
      

      现在,当重定向到 Search GET 操作时,默认模型绑定器将能够重建模型。这种方法的一个明显缺点是,如果您的模型具有许多属性,甚至复杂类型的属性更差,这可能很快成为一个繁琐的解决方案。您可能可以使用一些文本格式(例如 JSON)作为查询字符串参数来序列化模型。当然查询字符串参数在不同浏览器之间是有限的,所以这也可能是一个禁忌。

    3. 将模型保存在一些数据存储中并检索一个唯一的 id,以便以后可以从该存储中检索它:

      int id = Persist(model);
      return RedirectToAction("Search", new { id = id });
      

      然后在 GET 操作中使用 id 从这个相同的持久性存储中检索模型。我喜欢这种方法并且大部分时间都在使用它。如果持久化到上述 datastore 成本很高,您可以使用缓存。

    【讨论】:

    • 感谢您的建议。 #2 满足将参数值放入查询字符串的要求,但这确实看起来很麻烦,就像你说的那样。最后,我停止尝试与 MVC 作斗争,而是直接对查询字符串进行了尝试。
    【解决方案2】:

    您可以将需要保留的值放入 ControllerContext.RouteData.Values

        public ActionResult TestRedirect()
        {
            RouteValueDictionary routeValues = ControllerContext.RouteData.Values;
            routeValues.Add("Key1","value1");
            routeValues.Add("Key2","value2");
    
            return RedirectToAction("TargetRedirect", routeValues);
        }
    

    如果您需要更通用的东西,您可以遍历 postet 表单元素。

    编辑

    它看起来像这里评分最高的答案:How do you persist querystring values in asp.net mvc?

    【讨论】:

    • 我认为这行不通。它似乎丢失了所有其他查询字符串参数,除非我做错了什么。
    • 你是对的,现有的查询字符串参数不在 ControllerContext.RouteData.Values 中。您必须添加它们,我猜这不是您想要的。
    【解决方案3】:

    这可能违反了 MVC 原则,但是一旦我停止与框架抗争,只是想想我在 HTTP 领域尝试做什么,这个简单的解决方案就对我有用:

    [HttpPost]
    public ActionResult Search(PeopleGroupColumn filterField,
                               Operator filterOperator,
                               string filterValue)
    {
        var collection =
            HttpUtility.ParseQueryString(Request.QueryString.ToString());
        collection.Set(filterField.ToString(), filterValue);
        collection.Set(filterField.ToString() + "_op", filterOperator.ToString());
        return new RedirectResult(
            Request.Url.AbsolutePath + "?" + collection.ToString());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多