是否有可能在ASP.NET MVC路径到达控制器之前更改它的querystring变量?

时间:2010-12-30 00:05:00

标签: c# asp.net-mvc routing query-string asp.net-mvc-3

我在ASP.NET MVC中有一个控制器方法,如下所示:

public ActionResult GetAlbumPictures(int albumId)
{
    var album = AlbumRepo.GetSingle(albumId);
    var pictures = album.Pictures;
    return View(pictures);
}

此方法的路由如下所示:

routes.MapRoute(null,
                "pictures"
                new { controller = "Album", action = "GetAlbumPictures" });

用户将使用以下网址获取图片,按照相册ID进行过滤:

GET http://server/pictures?albumid=10

但是,我想将querystring参数更改为album而不是albumid

GET http://server/pictures?album=10

这意味着需要将控制器方法修改为:

public ActionResult GetPictures(int album)
{
    ...
}

但是,这并不理想,因为现在该方法有一个名为album的参数,可以将其混淆为Album 对象而不是ID Album

我的问题是,有没有办法配置ASP.NET MVC,以便在路由中,它将收到一个名为album的查询字符串参数,但随后将其作为{{1}传递给控制器参数?

P.S。我知道我可以在路由表中执行此操作:

albumId

但由于遗留问题,我必须使其适用于查询字符串方法。

4 个答案:

答案 0 :(得分:9)

您可以创建自定义操作过滤器属性来处理此方案。我没有测试过这个具体的实现,但总的想法是做这样的事情:

public class AlbumAttribute : ActionFilterAttribute
    {
         public override void OnActionExecuting(ActionExecutingContext filterContext)
         {
             var albumId = filterContext.HttpContext.Request.QueryString["album"] as string;
             filterContext.ActionParameters["albumId"] = albumId;

             base.OnActionExecuting(filterContext);
         }
    }

然后,使用[Album]属性修饰您的动作方法:

[Album]
public ActionResult GetAlbumPictures(int albumId)
{
    var album = AlbumRepo.GetSingle(albumId);
    var pictures = album.Pictures;
    return View(pictures);
}

答案 1 :(得分:0)

您可以使用自定义模型Binder,它可以同时使用album和albumId。 它可以实现如下:

自定义模型Binder:

public class AlbumModelBinder : IModelBinder
{
    public object BindModel
    (ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        int albumId;
        var albumVar = bindingContext.ValueProvider.GetValue( "album" );
        if (albumVar != null)
        {
            albumId = int.Parse( albumVar.AttemptedValue );
        }
        else
        {
            albumId = int.Parse( bindingContext.ValueProvider.GetValue( "albumId" ).AttemptedValue );
        }
        return albumId;
    }
}

行动实施:

public ActionResult GetAlbumPictures
([ModelBinder( typeof( AlbumModelBinder ) )] int albumId)
{
    var album = AlbumRepo.GetSingle(albumId);
    var pictures = album.Pictures;
    return View(pictures);
} 

Global.asax.cs实施:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    ModelBinders.Binders.Add( typeof( int ), new AlbumModelBinder() );
    RegisterRoutes( RouteTable.Routes );
}

答案 2 :(得分:0)

考虑拦截您的请求并使用HttpContext.RewritePath在路由引擎选择之前更改查询字符串。这里有一个很好的图表,显示了如何在路由之前执行Url重写:)

http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/

答案 3 :(得分:-1)

您可以在global.asax中的Application_BeginRequest中访问控制器之前拦截请求。您将无法访问MVC上下文,但可以使用

Server.Transfer(...);

Response.Redirect(...); 
Response.End();