代码之家  ›  专栏  ›  技术社区  ›  Jason Bunting

如何从保存的数据重建ASP.NET MVC中的URL/路由?

  •  2
  • Jason Bunting  · 技术社区  · 16 年前

    我对ASP.NET MVC框架及其管道系统的不熟悉使我来到这里,我感谢任何人阅读和考虑我的问题所需要的耐心!

    好的,这里是场景:我有一个应用程序,它有许多页面,其中的网格显示基于搜索的数据、从其他数据向下钻取的数据、基于上下文特定数据的报告(即,它们位于foo的详细信息页面上,然后单击显示与foo相关的数据表的链接)等等。

    在应用程序的所有页面中,用户可以通过给“报告”或网格命名和描述来保存它。这并不真正保存网格中显示的数据,而是保存定义网格外观的参数,保存用于 得到 数据,并保存在应用程序中定义“位置”的参数(操作、控制器、路由),基本上是关于报表/网格以及如何构建它的一组元数据。

    所有这些保存的报告都在一个列表中提供,在应用程序的某个页面上显示名称和说明,每个链接都指向一个通用的URL,如“/report s/saved/248”(其中248是报告ID的示例)。

    以下是我需要帮助的部分:

    当我通过url“/reports/saved/248”访问该操作并将元数据从该特定报表的数据库中拉出时,如何将该数据和请求重定向到用于显示报表最初保存的视图的相同操作、控制器和路由?本质上,我希望用户在同一视图中查看报告,使用与保存报告时相同的URL。如果可能的话,我会很高兴能够基本上“调用”相同的操作,就像我正在进行方法调用一样。


    更新:不幸的是,我们的报告页面(即这些网格显示的页面)没有使用RESTful URL-例如,我们有一个我们称之为高级搜索页面的页面,它使用大量来自包含选择列表、文本框等的表单的潜在参数(近30个)。当用户提交该页面时,我们会向接受模型绑定器为我们生成的复杂类型的操作-当用户从数据库中选择保存的高级搜索时,我想调用相同的操作。这个例子概括了我的问题。

    谢谢

    2 回复  |  直到 12 年前
        1
  •  2
  •   tvanfosson    16 年前

    我认为您需要使用带有RouteValueDictionary签名的RedirectToAction。您要重定向到的方法需要能够从控制器上的ValueProvider中提取值。它可能看起来像:

    public ActionResult Saved( int id )
    {
        var reportParams = db.Reports.SingleOrDefault( r => r.ID == id );
        if (reportParams == null)
           ...handle error...
    
        var routeValues = ParamsToRouteValueDictionary( reportParams );
    
        return RedirectToAction( reportParams.Action, reportParams.Controller, routeValues );
    }
    
    private RouteValueDictionary ParamsToRouteValueDictionary( object parameters )
    {
         var values = new RouteValueDictionary();
         var properties = parameters.GetType().GetProperties()
                                    .Where( p => p.Name != "Action" && p.Name != "Controller" );
         foreach (var prop in properties)
         {
             values.Add( prop.Name, prop.GetValue(parameters,null) );
         }
    
         return values;
    }
    

    编辑

    使用一个过滤器模型作为方法的参数实际上可能会更容易。你只需要得到并发布你的操作的版本。

     [ActionName("People")]
     [AcceptVerbs( HttpVerbs.Get )]
     public ActionResult PeopleDisplay( SearchModel filter )
     {
         return People( filter );
     }
    
     [AcceptVerbs( HttpVerbs.Post)]
     [ValidateAntiForgeryToken]
     public ActionResult People( SearchModel filter )
     {
         ....
     }
    

    然后将过滤参数(按名称)、操作(“人员”)和控制器存储在数据库中,用于报告。重定向结果将使用get并定向到peopleDisplay方法,而peopleDisplay方法又使用正确的参数调用people方法。从表单中发布直接调用People方法。使用两种方法可以使用CSRF预防机制。您可能可以使用tempdata中的标志来确保只有在需要限制对get操作的访问时,才通过重定向机制调用get操作。

    结束编辑

    另一种选择是简单地存储所使用的视图,而不是执行重定向,只渲染适当的视图。您需要考虑的一件事是,执行重定向最终将得到一个包含所有参数的URL,而呈现视图将使该URL保持独立,并且只显示与创建报表时使用的URL相同的视图。

        2
  •  0
  •   roryf    16 年前

    您可以使用RedirectToAction方法发布301重定向到任何控制器上的特定操作方法,以及路由值:

    ReportMeta meta = _reportDataAccess.Get(id);
    return RedirectToAction(meta.Action, meta.Controller, meta.RouteData);
    

    如果这些值类似于:

    meta.Action = "Bar";
    meta.Controller = "Foo";
    meta.RouteData = new {
        // possibly settings for the grid
        start = DateTime.Min,
        end = DateTime.Now,
        sort = "Date"
        // you get the idea
    };
    

    当然,我能看到的最直接的问题是,当控制器/操作方法随着时间的推移而改变时,报告数据将无效。但你可能已经想到了。