ASP.NET 4 WebApi: route with back slash - asp.net

I have a WebApi-route api/{type}({id})/{prop}
and I want to call it with url like /api/User(domain\username)/groups - the key point is "\" in id value. I send it from the client url-encoded i.e. as:
api/User(domain%5Cusername)/groups. But the route is ignored and I'm getting 404.
How to pass back slash into a route's argument?

As #ATerry suggested in comments the problem is not with ASP.NET but in HTTP.SYS + IIS. Back-slashes are replaced by HTTP.SYS onto forward-slashes even before coming to IIS.
We can work this around with help of UrlRewrite IIS-module as it has access to original (undecoded) url.
For my example I came up with the following rule.
<rule name="allow backslash" stopProcessing="true">
<match url="api/(.*)\((.*)\)(.*)" />
<action type="Rewrite" url="api/{R:1}({C:1}{C:2}{C:3}){R:3}" logRewrittenUrl="true" />
<conditions>
<add input="{UNENCODED_URL}" pattern="\((.*)(%5C)(.*)\)" />
</conditions>
</rule>
It's not ideal as it's very specific. It'd more useful to have a generic rule which just processes %5C.
The idea is to catch an url with %5C and rewrite it to put it back. It's a little bit weird but it works.
Besides the rule we need to set allowDoubleEscaping=false in system.webServer/security/requestFiltering:
<security>
<requestFiltering allowDoubleEscaping="true">
</requestFiltering>
</security>
With this rule the value come into a Mvc/Api controller will be encoded (with %). So we'll have to decode it:
public virtual DomainResult GetObjectProp(string type, string id, string prop)
{
id = Uri.UnescapeDataString(id);
}

Related

Regex to extract a part out of a URL and use it as a reference in url rewrite

OK, I'm wondering if someone can lend a hand with a regex I'm trying to write.
Basically, what I want to do is use IIS urlrewrite module to do a redirect to a specific URL if the user accesses a URL on another site. The only catch is I have to also capture a bit of the query string, and move it into the redirect. I think I actually DO have the regex correct for this, but it's implementing it in my web.config that is causing the problem.
so here is the input, the URL that a user may access would look like:
https://of.example.com/sfsv3.aspx?waform=pro&language=en
I want to match that URL (either http or https, case insensitive), and capture from it also one piece of information, the two letter language code. then the url i want to forward the user to looks like:
http://example.com/ca/en/ppf
(where en is replaced by whatever i captured above)
So, I'm working with IIS Rewrite module, and I've gotten my input data and regex in, so far the regex pattern I have is this:
https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))
so basically i'm matching the whole string, plus a group and a subgroup for language and it's code. in the IIS test pattern dialog, this is working.
I get the following
{R:1} language=en
{R:2} en
great! so then my IIS rewrite rule should look like this to redirect the user:
<system.webServer>
<rewrite>
<rules>
<rule name="test" stopProcessing="true" enabled="true">
<match url="https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))" ignoreCase="true" />
<action type="Redirect" url="http://www.example.com/ca/{R:2}/ppf" />
</rule>
</rules>
</rewrite>
</system.webServer>
this all seems right to me. however, IIS is balking and saying that my web.config is invalid. specifically, it says "Entity '(' is not defined" and it's pointing to the ( right before language as the problem. So, I can't build or deploy this application till I fix that. If i build it without and then just try to drop that into the web.config, i get an error loading the site:
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Can someone help me figure out how to put a capture group into a rewrite rule properly?
You forgot to code the ampersand. Should be:
<system.webServer>
<rewrite>
<rules>
<rule name="test" stopProcessing="true" enabled="true">
<match url="https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))" ignoreCase="true" />
<action type="Redirect" url="http://www.example.com/ca/{R:2}/ppf" />
</rule>
</rules>
</rewrite>

Regex to redirect a url using url rewrite

OK, I'm wondering if someone can lend a hand with a regex I'm trying to write.
Basically, what I want to do is use IIS urlrewrite module to do a redirect to a specific URL if the user accesses a URL on another site. The only catch is I have to also capture a bit of the query string, and move it into the redirect.
so here is the input, the URL that a user may access would look like:
https://of.example.com/sfsv3.aspx?waform=pro&language=en
I want to match that URL (either http or https, case insensitive), and capture from it also one piece of information, the two letter language code. then the url i want to forward the user to looks like:
http://example.com/ca/en/ppf
(where en is replaced by whatever i captured above)
So, I'm working with IIS Rewrite module, and I've gotten my input data and regex in, so far the regex pattern I have is this:
https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))
so basically i'm matching the whole string, plus a group and a subgroup for language and it's code. in the IIS test pattern dialog, this is working.
I get the following
{R:1} language=en
{R:2} en
great! so then my IIS rewrite rule should look like this to redirect the user:
<system.webServer>
<rewrite>
<rules>
<rule name="test" stopProcessing="true" enabled="true">
<match url="https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))" ignoreCase="true" />
<action type="Redirect" url="http://www.example.com/ca/{R:2}/ppf" />
</rule>
</rules>
</rewrite>
</system.webServer>
this all seems right to me. however, the redirect is not occurring. it seems to have a problem with the part \? (an escaped question mark to mark the start of the query string). if this is included, then the redirect simply does not happen.
Can you help me figure out how to get it work?
for the record, I figured it out. this is a special case of regex, running it inside a web.config as part of a urlrewrite action. in that case, you can't handle the query string with simple regex, you have to put in conditions on the query string. Here's what eventually ended up working:
<system.webServer>
<rewrite>
<rules>
<rule name="redirect" stopProcessing="true" stopProcessing="true" enabled="true">
<match url="sfsv3.aspx\.aspx" ignoreCase="true"/>
<conditions>
<add input="{QUERY_STRING}" pattern="subject=PROPRCH" />
<add input="{QUERY_STRING}" pattern="(..)/subject" />
</conditions>
<action type="Redirect" url="https://www.example.com/ca/{C:1}/forms/ppf" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
</system.webServer>

Using Url Rewrite to change REMOTE_ADDR works for files but not folders

I have a number of websites that make use of the REMOTE_ADDR server variable to record client IPs for metrics. In moving the hosting of these sites into a load balanced environment we're now only ever getting the load balancer IP in REMOTE_ADDR. I'm fully aware of the use of HTTP_X_FORWARDED_FOR and how it works and we do have access to it and my preferred solution is to simply update the applications to use it.
However, the powers that be here want to avoid having to update all of the websites :( I'm looking into alternatives in the mean time.
Ultimately this means finding some way of replacing REMOTE_ADDR with HTTP_X_FORWARDED_FOR before the request hits the applications.
I'm trying to get the URL Rewrite 2.0 module working using advice from another acole76's question here:
IIS 7 Rewrite web.config serverVariables directive not working in sub folder
My web.config is practically the same as his:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="RemoteHostRewrite">
<match url="(.*)" ignoreCase="true" />
<serverVariables>
<set name="REMOTE_ADDR" value="4.3.2.1" />
</serverVariables>
<action type="Rewrite" url="{R:0}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I'm using a hard-coded value 4.3.2.1 here for testing. I'll eventually replace that with the real value {HTTP_X_FORWARDED_FOR}.
Now, this works absolutely fine if a url contains a file name. It does not work if the url does not end with a file name.
For example:
mysite.local/default.aspx - works
mysite.local/ - does not work
mysite.local/folder/default.aspx - works
mysite.local/folder/ - does not work
I'm stumped! Can anyone offer any help?
you have to set another rule:
<match url="^$" />
<action type="Rewrite" url="/default.aspx" />
or whatever your default-page is
otherwise "url" will be empty --> no rule used

IIS7 Url Rewrite not being used

I'm rebuilding part of an existing asp application, the new parts are build with MVC.
One of the old screens which I'm not touching at the moment needs to point to a new location. For that reason I've set up a URL redirect in IIS on machine level with the following regular expression:
^workflows/screen\.asp\?objectid=([0-9]+)(.*)
When using the tester I can see that it's a correct expression which catches the necessary items and I need to send the users to the following new URL:
http://domainname/newapppart/select/{R:1}
When testing it in my browser though it seems as if the rewrite rule is not even in place as I'm still send to the old page.
Query string is not included in main match string, you have to use Conditions to evaluate it.
<rule name="MyRule" stopProcessing="true">
<match url="^workflows/screen\.asp$" />
<conditions trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="objectid=([0-9]+).*" />
</conditions>
<action type="Rewrite" url="http://domainname/newapppart/select/{C:1}" appendQueryString="false" />
</rule>

Creating Url Rewrite to a domain - ASP.NET \ IIS 7

I'm using ASP.NET 3.5 with IIS 7 with the URL Rewrite Module 2.0 installed.
When I create the first test rewrite rule:
<rewrite>
<rules>
<rule name="Test rule1" patternSyntax="ExactMatch">
<match url="w/123/test" />
<action type="Rewrite" url="article.aspx?id=123" />
</rule>
</rules>
</rewrite>
It works perfectly (http://www.myapp.com/w/123/test -> http://www.myapp.com/article.aspx?id=123).
BUT, when I try to use it on a domain that I own, it doesn't work. I assume that something in my syntax is wrong. Here is what i'm trying to do:
<rule name="Test Rule2" patternSyntax="ExactMatch">
<match url="http://www.my-domain.com" />
<action type="Rewrite" url="article.aspx?id=123" />
</rule>
When I try to browse http://www.my-domain.com I expect to be redirected to the article.aspx page, which I don't, I just get 404 page not found.
How should I write a rule for a domain and not for a path ?
Thanks in advance, Gal.
Rules are relative to the place where the web.config lives. You don't need to specify any domain for your rule. The input for your /> is going to be always the URL Path without the query string and without leading slash. That means, if you request "http://www.my-domain.com/" the input is going to be "". If you request "http://www.my-domain.com/w/123/test", the input would be "w/123/test".
If you just browse to http://www.my-domain.com/" the "Default Document" module in IIS will try to rewrite your request to something like http://www.my-domain.com/default.html" and that won't match your rule. Make sure to disable default document module.
If that doesn't work, URL Rewrite has a tracing feature where you can see step-by-step the workflow:
http://learn.iis.net/page.aspx/467/using-failed-request-tracing-to-trace-rewrite-rules/
N.B. For server rules, the input URL includes leading slash always.

Resources