Is it possible to change the querystring variable in an ASP.NET MVC path before it gets to the controller?

I have a controller method in ASP.NET MVC that looks like this:

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

The routing for this method is as follows:

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

The user will use the following URL to retrieve images filtered by album ID:

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

However, I would like to change the querystring parameter of only album instead of albumid :

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

This would mean that the controller method should be changed to:

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

However, this is not ideal, because now the method has a parameter called album , which can be confused as an album object instead of an ID album .

My question is, is there a way to configure ASP.NET MVC so that in routing it gets the querystring parameter named album , but then albumid it to the controller as the albumid parameter?

PS I know that I can do this in the routing table:

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

But due to obsolete issues, I have to get it working for the querystring method as well.

+4
source share
4 answers

You can create your own action filter attribute to handle this scenario. I have not tested this particular implementation, but the general idea is to do something like this:

 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); } } 

Next, decorate your action method with the [Album] attribute:

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

You can use the Custom Binder and work with the album and album. It can be implemented as follows:

User model binding:

 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; } } 

Act:

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

Global.asax.cs implementation:

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

Consider intercepting your request and use HttpContext.RewritePath to change the request string before it is selected by the routing engine. There is a good diagram here showing how Url Rewriting is done before routing starts :)

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

0
source

You can intercept the request before it hits the controller in Application_BeginRequest in your global.asax. However, you will not have access to MVC contexts, but you can use

 Server.Transfer(...); 

or

 Response.Redirect(...); Response.End(); 
-1
source

Source: https://habr.com/ru/post/1333748/


All Articles