How to Route to Url *with* Extension - asp.net

I'm trying to deliver my blog's sitemap.xml file generated by a Razor view, like so in my _AppStart.cshtml file:
//sitemap
RouteTable.Routes.MapWebPageRoute("sitemap.xml", "~/pages/shared/sitemap.cshtml");
This route is ignored for some reason, and I get a 404. It works fine if I route it to "/sitemap", but the moment I include the file extension it breaks. I'm assuming IIS is doing something with the request before ASP.NET gets hold of it, but I"m not sure what to do about it.

Try making the extension a parameter:
RouteTable.Routes.MapWebPageRoute(
"sitemap.{extension}", // route pattern
"~/pages/shared/sitemap.cshtml", // physical file
defaultValues: new {extension = "xml"}, // defaults
constraints: new {extension = "xml"}); // constraints (regex)

Related

openapi documentation how to handle extension in the path

I have URLs like:
/return/{pid}.xml?d1='123'&d2='345'
/return/{pid}.json?d1='123'&d2='345'
the swagger specification calls for:
path:/return/{pid}
....
but how can I map the extension ie
path:/return/{pid}.xml
or
path:/return/{pid}.json
It is a jersey+spring mvc application - so both the URLs are hitting the same controller and only based on the extension the rest framework is going to generate the xml / json output.
I can't ignore the extension from the path ie:
path:/return/{pid}
because the user needs to know that he/she has to provide the file extension as part of the URL. Also I can't use two paths corresponding to xml / json because they are treated the same by the application. In addition it will duplicate things (I am not sure whether there is a fall-through like mechanism just like "case" statements in c++/java "switch" block)
In Swagger specs,You can define the file extensions in the path as below :
/return/{pId}.{fileExtension}
and define the fileExtension in parameters .
also the below is valid (not for your case) :
/return/pid.{fileExtension}

UserManager.GenerateEmailConfirmationToken returning tokens unsuitable for URL transmission

I have a ASP.NET MVC 5 website, and I'm implementing an email confirmation process based on the template from Microsoft.
While I'm composing the email body text, first I construct the URL a user will use to "click to verify your address".
To generate the security token I call:
UserManager.GenerateEmailConfirmationTokenAsync(user.Id)
This produces a code such as:
pporPNj6KzdZ3BYG8vQsKJu3dPJMwGgh+ZEGhCNnf9X6F0AS0f6qCowOQwQNfpYkl14bgEsmyPTKya5H6N4n2na2n5PgO+wpoihXxQTA7G8pK/lUYskX3jy2iA/ZM8m4Vm0prTyUuhMgfDlV+wkbR336FBRIAbKJDwOWvHHbJBDQ21gW93hyzca0li66aI1H
Obviously, this wouldn't be valid in a URL, but even URL encoding won't solve IIS's hate of such a URL.
HTTP Error 404.11 - Not Found
The request filtering module is configured to deny a request that contains a double escape sequence.
In my UserManager implementation, I'm using the tutorial boilerplate code for a TokenProvider.
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<SiteUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
How can I make these generated tokens a bit more URL friendly? What did potentially change that would prevent the ASP.NET's tutorial code not work?
It turns out that this token will get mangled by the built in class "UrlHelper" in a MVC controller, or Url in a WebAPI controller IF the target route lists these variables as part of the path, rather than the GET vars of the URL.
Eg: this call, creates a relative URL for the site route called "ConfirmEmail" and fills in the blanks
Url.Route("ConfirmEmail", new { userId = user.Id, code = code });
Before my route was:
[Route("register-email/{code}/{userId}", Name = "ConfirmEmail")]
Changing this to:
[Route("register-email", Name = "ConfirmEmail")]
Generates valid URLS that IIS can chew through. When these are not specified, they get appended after a ? mark as normal GET vars. No idea why IIS is picky like that, but there's the solution.

ASP.NET URL Routing with wildcard

I have a CMS system that I am using Routing to get the page name. I have the need to have unlimited values (sub directories, product names, different localizations) between the first item and the last item (page name).
For example:
/Products/Computers/ComputerType1/
And
/Productos/Ordenadores/ComputerType1/
Where ComputerType1 is the page name.
routes.Add(new Route("{*route}/{pageName}", routeHandler));
I cannot find a way to make the middle part ({*route}) of the route to be the wildcard so that unlimited number of sub directories can be put in front of the page name. Currently I have only been able to get around this with having a default wildcard route such as:
routes.Add(new Route("{*route}", routeHandler));
to catch everything. However, the wildcard seems to also be letting in gif urls even thou I have it specified as ignore above in the route code as:
routes.Ignore("{resource}.axd/{*pathInfo}");
routes.Ignore("{resource}.asmx/{*pathInfo}");
routes.Ignore("{resource}.ashx/{*pathInfo}");
routes.Ignore("{resource}.gif/{*pathInfo}");
routes.Ignore("{resource}.png/{*pathInfo}");
routes.Ignore("{resource}.jpg/{*pathInfo}");
routes.Ignore("{resource}.ico/{*pathInfo}");
routes.Ignore("{resource}.pdf/{*pathInfo}");
routes.Ignore("{resource}.css/{*pathInfo}");
routes.Ignore("{resource}.js/{*pathInfo}");
Is there a better way of doing this? Should this be handled thru a custom route handler?
yes you should create a route handler for cases like these
simple create a class and derive it from RouteBase
override the GetRouteData method
in this method you can access the current httpcontext and thus you can access the requested URL
so u can route accordingly.
for more info on custom routes visit this link
http://www.codeproject.com/Articles/299531/Custom-routes-for-MVC-Application

IgnoreRoute with webservice - Exclude asmx URLs from routing

Im adding the filevistacontrol to my asp.net MVC web application.
I have a media.aspx page that is ignored in the routing with
routes.IgnoreRoute("media.aspx");
This works successfully and serves a standard webforms page.
Upon adding the filevistacontrol, I can't seem to ignore any calls the control makes to it's webservice.
Eg the following ignoreRoute still seems to get picked up by the MvcHandler.
routes.IgnoreRoute("FileVistaControl/filevista.asmx/GetLanguageFile/");
The exception thrown is:
'The RouteData must contain an item named 'controller' with a non-empty string value'
Thanks in advance.
Short answer:
routes.IgnoreRoute( "{*url}", new { url = #".*\.asmx(/.*)?" } );
Long answer:
If your service can be in any level of a path, none of these options will work for all possible .asmx services:
routes.IgnoreRoute("{resource}.asmx/{*pathInfo}");
routes.IgnoreRoute("{directory}/{resource}.asmx/{*pathInfo}");
By default, the parameters in a route pattern will match until they find a slash.
If the parameter starts with a star *, like pathInfo in those answers, it will match everything, including slashes.
So:
the first answer will only work for .asmx services in the root path, becasuse {resource} will not match slashes. (Would work for something like http://example.com/weather.asmx/forecast)
the second one will only work for .asmx services which are one level away from the root.{directory} will match the first segment of the path, and {resource} the name of the service. (Would work for something like http://example.com/services/weather.asmx/forecast)
None would work for http://example.com/services/weather/weather.asmx/forecast)
The solution is using another overload of the IgnoreRoute method which allows to specify constraints. Using this solution you can use a simple pattern which matches all the url, like this: {*url}. Then you only have to set a constraint which checks that this url refers to a .asmx service. This constraint can be expressed with a regex like this: .*\.asmx(/.*)?. This regex matches any string which ends with .asmx optionally followed by an slash and any number of characters after it.
So, the final answer is this:
routes.IgnoreRoute( "{*url}", new { url = #".*\.asmx(/.*)?" } );
I got it to work using this (a combo of other answers):
routes.IgnoreRoute("{directory}/{resource}.asmx/{*pathInfo}");
What happens when you use:
routes.IgnoreRoute("FileVistaControl/filevista.asmx");
If that doesn't work, try using the ASP.NET Routing Debugger to help you:
http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Try this:
routes.IgnoreRoute("{*filevista}", new { filevista = #"(.*/)?filevista.asmx(/.*)?" });
This is based on a Phil Haack recommendation stated here.
Have you tried:
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.IgnoreRoute("{resource}.asmx/{*pathInfo}");
It would help if you posted the source for your route configuration. I'm going to take a shot in the dark and say to make sure that your IgnoreRoute() calls are all at the top of your routing definition.
The way IgnoreRoute works is to create a route that matches the ignored route URL and constraints, and attaches a StopRoutingHandler as the RouteHandler. The UrlRoutingModule knows that a StopRoutingHandler means it shouldn't route the request.
As we know, the routes are matched in the order of which they are defined. So, if your {controller}/{action}/{id} route appears before your "FileVistaControl/filevista.asmx/GetLanguageFile/" route, then it will match the "{controller}/{action}/{id}" route.
I may be totally off base here, but it's hard to know without seeing your source. Hope this helps. And post source code! You'll get better answers.

Rewrite urls from user submitted HTML

I use one WYSIWYG editor in a small cms. It allows users to upload files, images, etc. If I add image named dog.jpg, in source I'll get:
<img src="/myweb/userfiles/images/dog.jpg" />
I can save this to a database and use it later on any page, until I move my site to a live domain.
myweb is virtual directory in IIS. "/" points to root, in this case localhost, so I have to use "/myweb". However when I upload site to server and copy database there, all links will be broken, because there is no "myweb" folder on server.
My idea was to replace "/myweb" on save with empty string. I also have to replace full url, which editor creates for some files. On display I would have to add correct Application dir. I would probably save both versions in database, and only on server change force display version to update.
By now I've come up with:
p = p.Replace("href=\"" + fullUrl, "href=\"").Replace("src=\"" + fullUrl, "src=\"").Replace("href=\"" + partialUrl, "href=\"").Replace("src=\"" + partialUrl, "src=\"");
Which is ugly, hard to maintain and inefficient. I guess better approach would be to use regex, but I don't know how to do it.
My question is, can anyone recommend good article, blog/forum post on this? If you have other solution, great.
I am unsure the regex version has any of the characteristics you mention in this case.
That said, you can do:
string ReplaceUrlPaths(string html, string partialPath, string fullPath)
{
var pattern = string.Format("((href|src)=\")({0}|{1})", partialPath, fullPath);
var regex = new Regex(pattern);
return regex.Replace(html, m => m.Groups[1].Value);
}
[TestMethod]
public void TestMethod10()
{
var input = #"<img src=""/myweb/userfiles/images/dog.jpg"" />";
//carefull with any special regex char in the paths
var replaced = ReplaceUrlPaths(input, "/myweb", "/some/full/path");
Assert.AreEqual(
#"<img src=""/userfiles/images/dog.jpg"" />",
replaced);
}
If you are proceeding with that, refactor it to instantiate the regex once with the compile option(as the partialPath and fullPath won't be changing).
Also consider avoiding it all, by defining a web site with an alternate port to just have it as a root Url.
Store the local root path separately from the images. For each image, store the relative path to that image.
When displaying images locally, use the local root merged with the relative path. When you publish to the remote server, you add the remote root to the relative path.
Does your WYSIWYG editor allow you to configure the base URL e.g. so that paths to images can use relative paths? I think the FCKEditor has something like FCKConfig.BaseHref in it's config file that does something like this.
Alternatively can you run the site as a root site using the ASP.NET 2.0 web server? Then you wouldn't have to worry about rewriting paths to images as you could just use paths from the webroot.

Resources