How to do URL Rewriting without query parameter doubling its value? - c#

I have to following URL:
http://example.org/sessionstuff/kees/view.aspx?contentid=4&itemid=5
It needs to be rewritten so it will go to:
http://example.org/sessionstuff/view.aspx?site=kees&contentid=4&itemid=5
Basically it will take the kees value and put it as a site parameter. I'm using the IIS URL Rewrite module that uses rules in my web.config. I've added the following code to my web.config:
<rule name="RedirectSite" stopProcessing="true">
<match url="^(\D[^/]*)/(.*)$" />
<action type="Rewrite" url="{R:2}?site={R:1}" />
</rule>
Everything works fine, but when I do a postback, the site parameter is doubled. I've tested this by using the following code on my .aspx page:
<h3>Querystring</h3>
<ul>
<% foreach (string key in Request.QueryString.Keys)
Response.Write(String.Format("<li><label>{0}:</label>{1}</li>", key, Request.QueryString[key])); %>
</ul>
<asp:Button runat="server" Text="Postback" />
First time
Querystring
site: kees
contentid: 4
itemid: 5
Second time
Querystring
site: kees, kees <--- double
contentid: 4
itemid: 5
How to prevent the site parameter from duplicating itself? Each postback will add another value.
Note: the other query parameters must be present, so using appendQueryString="false" seems not an option.

It looks like this could be solved by not rewriting the URL if it already contains the site= parameter (regardless of where in the query string it's located). So how do we do that?
Check out number 9 here: http://ruslany.net/2009/04/10-url-rewriting-tips-and-tricks/
I don't have a way to test this now, but I reckon something like this should work:
<rule name="Query String Rewrite">
  <match url="^(\D[^/]*)/(.*)$" />
  <conditions>
    <add input="{QUERY_STRING}" pattern="^((?!site=).)*$" />
  </conditions>
<action type="Rewrite" url="{R:2}?site={R:1}" />
</rule>
NOTE: I am not great at rule rewriting, but this regex ^((?!site=).)*$ matches when the string DOES NOT contain site= and this is when you want your rewrite rule to operate, hence me adding that as a condition. I reckon you may be able to do this more efficiently.
What I am trying to do here is say: Let's rewrite the rule, but only if it doesn't already contain the site parameter.
I hope this is enough for you to answer the question!
===
This seems to work:
<rule name="RedirectSite" stopProcessing="true">
<match url="^(\D[^/]*)/(.*)$" />
<conditions>
<add input="{QUERY_STRING}" pattern="^((?!site=).)*$" />
</conditions>
<action type="Rewrite" url="{R:2}?site={R:1}" />
</rule>
<rule name="RedirectSite2" stopProcessing="true">
<match url="^(\D[^/]*)/(.*)$" />
<conditions>
<add input="{QUERY_STRING}" pattern="site=" />
</conditions>
<action type="Rewrite" url="{R:2}" />
</rule>

Related

IIS redirect rule with regex inside condition

I get 500 error when having this rule:
<rule name="Remove Query String" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{QUERY_STRING}" pattern="^url=[^&]+" />
</conditions>
<action type="Redirect" url="{C:1}webp" appendQueryString="false" />
Problem is inside
<add input="{QUERY_STRING}" pattern="^url=[^&]+" />,
actually pattern seems wrong but works corrently when I check it online. All parsers parse it.
What I want to achieve is to redirect all URL that have query string url= to url whose value corresponds to the value of url in initial request but ignroeing everything after &, or everything after something else (like webp for example) That is reason I want to separate pattern in multiple logical groups.

If user is coming from domain testx.com, rewrite url to mydomain.com/testx

I have an ASP.Net website, but several domain names are pointing to the same website.
so for example lets say i have following domains
www.myMainDomain.com
www.mySite1.com
www.mySite2.com
I have 1 actual website with all the pages and subpages i want to have.
www.myMainDomain.com
www.myMainDomain.com/site1
www.myMainDomain.com/site1/products
www.myMainDomain.com/site2
www.myMainDomain.com/site2/products
...
So i would like to have a rewrite rule in my web.config
so that if the user is coming from the www.myMainDomain.com, it is just the normal site as it is existing
but if they are coming from www.mySite1.com, the rewrite rule should kind of take them to www.myMainDomain.com/site1, and if they go to a subpage, like products, it is always rewritten so like this
www.mySite1.com -> www.myMainDomain.com/site1
www.mySite1.com/products -> www.myMainDomain.com/site1/products
I have something like that, but this is not working, and it is actually causing a 500 Error
<system.webServer>
<rewrite xdt:Transform="Insert">
<rules>
<rule name="Root Hit Redirect" stopProcessing="true">
<match url="^$" />
<action type="Redirect" url="/site1/{R:1}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
What could be a correct solution?
I think you could use the inverse of standard canonicalhostname redirect with some changes:
<rule name="CanonicalHostNameRule_Mod" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="^www\.mySite1\.com$" />
</conditions>
<action type="Redirect" url="http://www.myMainDomain.com/site1/{R:1}" />
</rule>
In this way you have to make a rule for each secondary domain.

Query string is broken when white space is added to parameter

I've got the following url:
inspiratie/color-collections/test/test/S%200502-B/test
And the rewrite rule within the web.config:
<rule name="color2">
<match url="(kleur-en-inspiratie|inspiratie)/color-collections/([\S ^/]+)/([\S ^/]+)/([\S ^/]+)(/)?([\S ^/]*)" />
<action type="Rewrite" logRewrittenUrl="true" appendQueryString="false" url="{R:1}/color-collections/color-detail?colorcollection={R:2}&colorfamily={R:3}&color={R:4}&colorname={R:6}" />
</rule>
After the rule kicks in, the url becomes:
inspiratie/color-collections?colorcollection=test&colorfamily=test&color=S&colorname=
But the expected output would be:
inspiratie/color-collections?colorcollection=test&colorfamily=test&color=S 0502-B&colorname=test
As you can see if the space is used within the color code, the query string is broken after the color param ({R:4}).
When I test the rule within IIS, it works fine and returns the expected results.
I know that the unescaped white space will not work, but expecting the escaped one to work.
In your case problem cause because of encoding. You need to use {UNENCODED_URL} variable for regexp. Rule should be like that:
<rule name="color2">
<match url=".*" />
<conditions>
<add input="{UNENCODED_URL}" pattern="(kleur-en-inspiratie|inspiratie)/color-collections/([\S ^/]+)/([\S ^/]+)/([\S ^/]+)(/)?([\S ^/]*)" />
</conditions>
<action type="Rewrite" logRewrittenUrl="true" appendQueryString="false" url="{C:1}/color-collections/color-detail?colorcollection={C:2}&colorfamily={C:3}&color={C:4}&colorname={C:6}" />
</rule>

Custom ServerVariable IIS

i am trying to create a custom servervariable with url rewrite.
Url Rewrite for IIS generates the following config entry
<rewrite>
<rules>
<rule name="CName to URL - Rewrite" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(?!www)(.*)\.localfurnco\.de" />
</conditions>
<action type="Rewrite" url="?" appendQueryString="false" />
<serverVariables>
<set name="HTTP_MANUFACTURER" value="{C:1}" />
</serverVariables>
</rule>
</rules>
</rewrite>
But when iterating through the servervariables i can't find HTTP_MANUFACTURER.
The url rewrite seems to work but i can't get the Variable.
I am trying to call the address: test.localfurnco.de/subdir/webservice.asmx?wsdl.
C:1 should in this case be: "test".
I would be grateful for any suggestion and
thanks in advance
After trying some hours i figured it out myself.
Here is the resulting rule.
<rule name="CName to URL - Rewrite" stopProcessing="false">
<match url=".*" negate="false" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{SERVER_NAME}" pattern="^(?!www)(.*)\.localfurnco\.de" />
</conditions>
<action type="Rewrite" url="?CustomValue={C:1}" logRewrittenUrl="true" />
<serverVariables>
<set name="HTTP_MANUFACTURER" value="{C:1}" />
</serverVariables>
</rule>
With this rule it is possible to access the ServerVariable "HTTP_MANUFACTURER" from C#:
string variable= httpContext.Current.Request.ServerVariables.Get("HTTP_MANUFACTURER");
A Different option a friend shared with me is this:
string value= HttpContext.Current.Request.Params.Get("CustomValue");
As you can see i rewrite the url and set a parameter which i assign the, by the pattern, filtered value.
I hope this helps somebody else.

Manually append query string using Url Rewrite in IIS

I'm trying to create a rewrite rule such as:
~/company_search.aspx?cat=987&page=2&loc=1234
to
~/company_category/987/estiatoria/?loc=1234&page=2
My rewrite rule is:
<rule name="Company Category">
<match url="company_category/([0-9]+)/(?:[^/]*)/?" />
<action type="Rewrite" url="company_search.aspx?cat={R:1}" appendQueryString="true" />
</rule>
The part /estiatoria/ in the sample rewritten url is optional for seo optimization and not specified in the actual querystring neither has any other use. When I do a postback I get the cat parameter 2 times with a value 987,987 and my server-side code gets messed up.
So I tried to manually append the querystring in order to exclude the cat parameter and append all the others. So I changed the rule to:
<rule name="Company Category">
<match url="company_category/([0-9]+)/(?:[^/]*)/?(?:\?|&)?(.*)" />
<action type="Rewrite" url="company_search.aspx?cat={R:1}&{R:2}" appendQueryString="false" />
</rule>
But I don't get any other values in the querystring except cat. Am I doing something wrong?
Update:
I think I must add a querystring condition in order to exclude the cat parameter and then append the rest matching result. So for the querystring:
?cat=987&page=2&loc=1234
I'd like to get:
?page=2&loc=1234
and the cat parameter could be in any order or not present.
I tried:
<rule name="Company Categories Search">
<match url="company_category/([0-9]+)/(?:[^/]*)/?" />
<conditions>
<add input="{QUERY_STRING}" pattern="(?!cat=[0-9]+)(.*)(cat=[0-9]+|$)(?!cat=[0-9]+)(.*)" />
</conditions>
<action type="Rewrite" url="company_search.aspx?cat={R:1}&{C:1}&{C:3}" appendQueryString="false" />
</rule>
When I hit the url:
~/company_category/987/estiatoria/?page=2&loc=1234
I get on the server side Request.Querystring the following value:
cat=987&page=2&loc=1234&
but when I do a postback I get:
cat=987&at=987&page=2&loc=1234&
Can someone please help me with that last regex condition?
Update 2:
I've come to a solution but it doesn't cover every scenario:
<rule name="Company Categories Search">
<match url="company_category/([0-9]+)/(?:[^/]*)/?" />
<conditions logicalGrouping="MatchAny">
<add input="{QUERY_STRING}" pattern="(cat=[0-9]+)(.*)" />
<add input="{QUERY_STRING}" pattern="(^)(.*)" />
</conditions>
<action type="Rewrite" url="company_search.aspx?cat={R:1}&{C:2}" appendQueryString="false" />
</rule>
I've used 2 condition rules with MatchAny option in order to match one: the query string when the cat value is present in the mapped url (currently only in postbacks) and two: when it's not present.
If the cat parameter is somehow between page and loc parameters the previous parameter is not included in the query string. If anyone has a better solution please let me know.

Categories