Url routing is not working? - iis-7

web.config for url rewrite is
<rewrite>
<rules>
<rule name="Mobile Portal">
<match url="^(code)(/)?([^']*)" />
<action type="Redirect" url="Code.aspx?id={R:3}" />
</rule>
</rules>
</rewrite>
input: www.abc.com/Code.aspx?id=123abcdef
Required output: www.abc.com/code/123abcdef
current output: http://www.abc.com/Code.aspx?id=.aspx
The valid page url is www.abc.com/code/123abc . I need "123abc" . When I am accessing the page by www.abc.com/code/123abc, the url is converted to "http://www.abc.com/Code.aspx?id=.aspx ".I am using IIS 7. So how can I fix this issue?
Thanks a lot in advance.

You can use url routing instead of url rewriting. for this purpose go to Global.asax file and write RegisterRoutes method like this :
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("my_abc_page",
"code/{id}",
"~/Code.aspx");
}
with above command, any request like www.abc.com/code/123abcdef interpret to www.abc.com/Code.aspx?id=123abcdef and you can access to this id in code of your page :
theId = Page.RouteData.Values["id"] as string;

Related

edit Global.asax file and implement it in website

I have website running which contains Global.asax file and App_global.asax.compiled also App_global.asax.dll but now i want to edit or add some existing code of url rewriting.
but when i do code in global.asax file it is not taking.
After lot of googling and search's i come to know i have to compile that global file again after changes done. but i cant do it as the websi## Heading ##te is live and i dont have the solution for it.
Existing code in Global.asax:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext myContext=HttpContext.Current;
Regex rewrite_regex = new Regex(#"(.+)\/((.+)\.*)", RegexOptions.IgnoreCase);
try
{
// 'see if we need to rewrite the URL
Match match_rewrite =rewrite_regex.Match(myContext.Request.Path.ToString());
string str = match_rewrite.Groups[2].Captures[0].ToString();
string root = match_rewrite.Groups[0].Captures[0].ToString();
if (Regex.Match(root, "/News/", RegexOptions.IgnoreCase).Success)
{
myContext.RewritePath("~/Default2.aspx?nid="+str);
}
else if (Regex.Match(root, "/Search/", RegexOptions.IgnoreCase).Success)
{
myContext.RewritePath("~/Default.aspx?text=" + str);
}
else if (Regex.Match(root, "/Find/", RegexOptions.IgnoreCase).Success)
{
myContext.RewritePath("~/Default.aspx?text=" + str);
}
Any help will be greatful.
Since you don't have the code the easier way will be to use the IIS redirect rules?
This will add the rules to your web.config. You can create multiple regex-based rules to satisfy your different conditions
e.g.
<rule name="Redirect from blog">
<match url="^blog/([_0-9a-z-]+)/([0-9]+)" />
<action type="Redirect" url="article/{R:2}/{R:1}" redirectType="Found" />
</rule>

Preventing CSRF with the same-site cookie attribute

I was surfing the web and found article Preventing CSRF with the same-site cookie attribute.
As on link maintain We need to add Set-Cookie header.
Set-Cookie: key=value; HttpOnly; SameSite=strict
Now My Question is, I want to set this in my ASP.NET site in all Cookies and Authentication Cookie.
I tried to set this using header from IIS but someone says this is wrong way implementation.
I have also tried below.
HttpCookie newAuthenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName
, FormsAuthentication.Encrypt(newAuthenticationTicket))
{
HttpOnly = true
};
newAuthenticationCookie.Values.Add("SameSite", "strict");
But it seems like not helping me.
Please suggest me a better way to do this.
Thanks.
After Deep review on HttpCookie Source it's confirm that we cannot do this with the code, as there is no way to add extra attribute on Cookie and class is marked as sealed.
But still anyhow I manage solution by modifying web.config as below.
<rewrite>
<outboundRules>
<rule name="Add SameSite" preCondition="No SameSite">
<match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
<action type="Rewrite" value="{R:0}; SameSite=strict" />
<conditions>
</conditions>
</rule>
<preConditions>
<preCondition name="No SameSite">
<add input="{RESPONSE_Set_Cookie}" pattern="." />
<add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=strict" negate="true" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
This add SameSite=strict on each Set-Cookie.
You can also set this in code when creating a cookie:
var httpCookie = new HttpCookie("mycookie", "myvalue");
httpCookie.Path += ";SameSite=Strict";
Response.SetCookie(httpCookie);
This will give you the following header:
Set-Cookie:mycookie=myvalue; path=/;SameSite=Strict
bit of a hack until it's pushed in to the framework.
Just adding my answer to systematize all the info found here and in other places.
1. To secure custom cookies under 4.7.2 and later
var c = new HttpCookie("test");
c.SameSite = SameSiteMode.Lax;
2. To secure Forms authentication cookie
In web.config
<authentication mode="Forms">
<forms ..... cookieSameSite="Lax" />
</authentication>
3. To secure ASP.NET Session cookie
In Global.asax
void Session_Start(Object sender, EventArgs e)
{
Response.Cookies["ASP.NET_SessionId"].SameSite = SameSiteMode.Lax;
//while we're at it lets also make it secure
if (Request.IsSecureConnection)
Response.Cookies["ASP.NET_SessionId"].Secure = true;
}
Fun fact: even if you set <httpCookies requireSSL="true" /> the ASP.NET session cookie will still be non-secure for some reason.
3(a). UPDATE 01.2020: .NET 4.8 Session cookie is now "SameSite" by default
Installing the latest Windows Update will make your session cookies Lax by default. You can control it here:
<sessionState cookieSameSite="Lax" /> <!-- in system.web -->
4. <httpCookies samesite=xxx> does not exist?
Adding <httpCookies sameSite="Strict" /> like suggested in the comment above in web.config didn't work, I was getting the error.
Unrecognized attribute 'samesite'
Even though I'm targeting 4.7.2. Tested on multiple project and multiple machines, also VS2019 does not show this in intellisense and MS docs do not mention it anywhere.
.NET 4.7.2 has now built-in support for SameSite property. The HttpCookie has now a property called SameSite. See more info here from Microsoft.
No need anymore to hack this through the config file.
In order to have SameSite defined to ASP.NET_SessionId cookie I had to set the web.config under system.web section:
<sessionState cookieSameSite="Lax" />
Because in this day and age we use owin to fix the same silly webapi cookie bug...
public class CookieSameSiteMiddleware : OwinMiddleware
{
public CookieSameSiteMiddleware(OwinMiddleware next) : base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
var url = context.Request.Path.Value.ToLowerInvariant();
if (url.Contains("/api/mylogin"))
{
context.Response.OnSendingHeaders(x =>
{
var scv = context.Response.Headers.FirstOrDefault(h => h.Key == "Set-Cookie");
if (!scv.Equals(default(KeyValuePair<string, string[]>)))
{
//context.Response.Headers.Remove("Set-Cookie");
context.Response.Headers.Set("Set-Cookie", scv.Value[0] + "; SameSite=strict");
}
}, null);
}
await this.Next.Invoke(context);
}
}
Make sure the middle-ware is registered before .UseWebApi()
Pre 4.7.2 you can just append the string to the cookie path.
FormsAuthentication.SetAuthCookie(username, false, FormsAuthentication.FormsCookiePath + "; SameSite=Lax");
https://www.nuget.org/packages/Microsoft.Owin.Security.Cookies/4.1.0 now supports SameSite.
That is very good news because the other solutions here doesn't work that brilliantly:
Implementing OwinMiddleware: Works great, except for performance. This might be something specific for our environment but that solution was about 10% of our CPU.
<outboundRules>: Probably possible to get working. But all solutions I've seen so far and we tested, including the one in this thread, had some issues when multiple cookies where set in the same response.

IIS 7 URL Rewrite returns blank pages for child requests

I am working with the following inbound rule:
<rule name="CrmInbound" enabled="true">
<match url="^crm/(.*)" />
<action type="Rewrite" url="http://myserver:1234/{R:1}" logRewrittenUrl="true" />
</rule>
When I browse to http://myserver/crm/ it does get converted properly, but when it goes to get the child pages and links, it gets a blank result. End result is a blank page with no errors.
What should be done to fix this? (ARR proxy is already enabled)
Here is the failed request log for the main request and then the subsequent request:
URL_REWRITE_START RequestURL="/crm/", Scope="Distributed", Type="Inbound"
RULE_EVALUATION_START RuleName="CrmInbound", RequestURL="crm/", QueryString="", PatternSyntax="Regex", StopProcessing="false", RelativePath="/"
PATTERN_MATCH Pattern="^crm/(.*)", Input="crm/", Negate="false", Matched="true"
REWRITE_ACTION Substitution="http://myserver:1234/{R:1}", RewriteURL="http://myserver:1234/", AppendQueryString="true", LogRewrittenURL="true"
RULE_EVALUATION_END RuleName="CrmInbound", RequestURL="http://myserver:1234/", QueryString="", StopProcessing="false", Succeeded="true"
GENERAL_SET_REQUEST_HEADER HeaderName="X-Original-URL", HeaderValue="/crm/", Replace="true"
URL_CHANGED OldUrl="/crm/", NewUrl="http://myserver:1234/"
URL_REWRITE_END RequestURL="http://myserver:1234/"
Subsequent
URL_REWRITE_START RequestURL="/COCRM/_common/styles/fonts.css.aspx?lcid=1033&ver=768231620", Scope="Distributed", Type="Inbound"
RULE_EVALUATION_START RuleName="CrmInbound", RequestURL="COCRM/_common/styles/fonts.css.aspx", QueryString="lcid=1033&ver=768231620", PatternSyntax="Regex", StopProcessing="false", RelativePath="/"
PATTERN_MATCH Pattern="^crm/(.*)", Input="COCRM/_common/styles/fonts.css.aspx", Negate="false", Matched="false"
RULE_EVALUATION_END RuleName="CrmInbound", RequestURL="COCRM/_common/styles/fonts.css.aspx", QueryString="?lcid=1033&ver=768231620", StopProcessing="false", Succeeded="false"
URL_REWRITE_END RequestURL=""

conditional url routing with asp.net 4 webforms

I want to server mobile and web version of pages on my site without any redirection so that if visitor browse them with PC they would see web version and vice versa.
I can do some media queries and reduce stuff on the page but that is not ideal.
I know i can do it with asp.net mvc, but, project is already half finished and I don't have time to rewrite it.
I thought about using conditional routing but as routes register on application start it didn't look possible. Is there anyway using conditional roting?
I am open to suggestions too.
This isn't an MVC solution, but I know you can do this with the IIS7 rewrite module.
<rewrite>
<rules>
<rule name="Mobile" stopProcessing="true">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAny">
<add input="{USER_AGENT}" pattern="iPhone" />
</conditions>
<action type="Rewrite" url="Mobile/{R:1}" />
</rule>
</rules>
</rewrite>
You could certainly also do this with a custom conditional route in MVC.
public class MobileConstraint : IRouteConstraint
{
public MobileConstraint() { }
public bool Match(HttpContextBase httpContext, Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection)
{
// add null checking etc
return httpContext.Request.UserAgent.Contains("iPhone")
}
}
context.MapRoute(
"mobile",
"Mobile/{controller}/{action}/{id}",
new { action = "Index", controller = "Home", id = UrlParameter.Optional },
new { controller = new MobileConstraint() }
);

Using ASP.NET routing to serve static files

Can ASP.Net routing (not MVC) be used to serve static files?
Say I want to route
http://domain.tld/static/picture.jpg
to
http://domain.tld/a/b/c/picture.jpg
and I want to do it dynamically in the sense that the rewritten URL is computed on the fly. I cannot set up a static route once and for all.
Anyway, I can create a route like this:
routes.Add(
"StaticRoute", new Route("static/{file}", new FileRouteHandler())
);
In the FileRouteHandler.ProcessRequest method I can rewrite the path from /static/picture.jpg to /a/b/c/picture.jpg. I then want to create a handler for static files. ASP.NET uses the StaticFileHandler for this purpose. Unfortunately, this class is internal. I have tried to create the handler using reflection and it actually works:
Assembly assembly = Assembly.GetAssembly(typeof(IHttpHandler));
Type staticFileHandlerType = assembly.GetType("System.Web.StaticFileHandler");
ConstructorInfo constructorInfo = staticFileHandlerType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
return (IHttpHandler) constructorInfo.Invoke(null);
But using internal types doesn't seem to be the proper solution. Another option is to implement my own StaticFileHandler, but doing so properly (supporting HTTP stuff like ranges and etags) is non-trivial.
How should I approach routing of static files in ASP.NET?
Why not use IIS to do this? You could create a redirect rule to point any requests from the first route to the second one before it even gets to your application. Because of this, it would be a quicker method for redirecting requests.
Assuming you have IIS7+, you would do something like...
<rule name="Redirect Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Redirect" url="/a/b/c/{R:1}" redirectType="Permanent" />
</rule>
Or, if you don't need to redirect, as suggested by #ni5ni6:
<rule name="Rewrite Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Rewrite" url="/a/b/c/{R:1}" />
</rule>
Edit 2015-06-17 for #RyanDawkins:
And if you're wondering where the rewrite rule goes, here is a map of its location in the web.config file.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- rules go below -->
<rule name="Redirect Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Redirect" url="/a/b/c/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
After digging through this problem for a few hours, I found that simply adding ignore rules will get your static files served.
In RegisterRoutes(RouteCollection routes), add the following ignore rules:
routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{file}.html");
I've had a similar problem. I ended up using HttpContext.RewritePath:
public class MyApplication : HttpApplication
{
private readonly Regex r = new Regex("^/static/(.*)$", RegexOptions.IgnoreCase);
public override void Init()
{
BeginRequest += OnBeginRequest;
}
protected void OnBeginRequest(object sender, EventArgs e)
{
var match = r.Match(Request.Url.AbsolutePath);
if (match.Success)
{
var fileName = match.Groups[1].Value;
Context.RewritePath(string.Format("/a/b/c/{0}", fileName));
}
}
}
I came up with an alternative to using the internal StaticFileHandler. In the IRouteHandler I call HttpServerUtility.Transfer:
public class FileRouteHandler : IRouteHandler {
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
String fileName = (String) requestContext.RouteData.Values["file"];
// Contrived example of mapping.
String routedPath = String.Format("/a/b/c/{0}", fileName);
HttpContext.Current.Server.Transfer(routedPath);
return null; // Never reached.
}
}
This is a hack. The IRouteHandler is supposed to return an IHttpHandler and not abort and transfer the current request. However, it does actually achieve what I want.
Using the internal StaticFileHandler is also somewhat a hack since I need reflection to get access to it, but at least there is some documentation on StaticFileHandler on MSDN making it a slightly more "official" class. Unfortunately I don't think it is possible to reflect on internal classes in a partial trust environment.
I will stick to using StaticFileHandler as I don't think it will get removed from ASP.NET in the foreseeable future.
You need to add TransferRequestHandler for handling your static files.Please see following answer
https://stackoverflow.com/a/21724783/22858

Resources