How do I match a URL starting with a literal tilde character (~) in System.Web.Routing / ASP.NET MVC?
I'm converting some old-school code to ASP.NET MVC, and have hit a snag caused by our URL formats. We specify thumbnail width, height, etc. in a URL by prefixing the special URL path with a tilde, as in this example:
http://www.mysite.com/photo/~200x400/crop/some_photo.jpg
At the moment, this is resolved by a custom 404 handler in IIS, but now I want to replace /photo/
with an ASP.NET and use System.Web.Routing
to extract the width, height, etc. from the incoming URL.
Problem is - I can't do this:
routes.MapRoute(
"ThumbnailWithFullFilename",
"~{width}x{height}/{fileNameWithoutExtension}.{extension}",
new { controller = "Photo"开发者_如何学运维, action = "Thumbnail" }
);
because System.Web.Routing won't allow a route to start with a tilde (~) character.
Changing the URL format isn't an option... we've supported this URL format publicly since 2000 and the web is probably rife with references to it. Can I add some kind of constrained wildcard to the route?
You could write a custom crop route:
public class CropRoute : Route
{
private static readonly string RoutePattern = "{size}/crop/{fileNameWithoutExtension}.{extension}";
private static readonly string SizePattern = @"^\~(?<width>[0-9]+)x(?<height>[0-9]+)$";
private static readonly Regex SizeRegex = new Regex(SizePattern, RegexOptions.Compiled);
public CropRoute(RouteValueDictionary defaults)
: base(
RoutePattern,
defaults,
new RouteValueDictionary(new
{
size = SizePattern
}),
new MvcRouteHandler()
)
{
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var rd = base.GetRouteData(httpContext);
if (rd == null)
{
return null;
}
var size = rd.Values["size"] as string;
if (size != null)
{
var match = SizeRegex.Match(size);
rd.Values["width"] = match.Groups["width"].Value;
rd.Values["height"] = match.Groups["height"].Value;
}
return rd;
}
}
which you would register like this:
routes.Add(
new CropRoute(
new RouteValueDictionary(new
{
controller = "Photo",
action = "Thumbnail"
})
)
);
and inside the Thumbnail
action of Photo
controller you should get all you need when you request /~200x400/crop/some_photo.jpg
:
public ActionResult Thumbnail(
string fileNameWithoutExtension,
string extension,
string width,
string height
)
{
...
}
精彩评论