URL Rewrite Default Document Web Page to SEO URL - asp.net

I have started using ASP.NET Routing for my site. I have been registering routes via the Application_Start() in my Global.asax file.
i.e.
routes.MapPageRoute("ROUTE-ABOUT", "about", "~/About.aspx");
routes.MapPageRoute("ROUTE-CONTACT", "contact", "~/Contact.aspx");
//etc...
This is working perfectly for the About and Contact pages.
What I Want:
My home page is Home.aspx and what I wanted to do is rewrite anyone that visits
http://localhost/mysite.com/Home.aspx
to
http://localhost/mysite.com/Home
What I've Tried
I have my site running in my local IIS v7.5 on my machine (full
administrator privileges).
I have added the following to my Web.config
Web.config
<rewrite>
<rules>
<rule name="HOMETOSEO" stopProcessing="true">
<match url="Home\.aspx" />
<action type="Redirect" url="home" appendQueryString="false" />
</rule>
</rules>
</rewrite>
Thanks in advance

After hours of trying to get this to work I eventually managed to get it working using the following entry in the Web.config and Application_Start() of the Global.asax file:
Web.config
<rewrite>
<rules>
<rule name="default" enabled="true" patternSyntax="ECMAScript" stopProcessing="false">
<match url="(.*)Home\.aspx" ignoreCase="true" />
<action type="Redirect" url="home" appendQueryString="false" />
</rule>
<rule name="lower" enabled="true" patternSyntax="ECMAScript" stopProcessing="true">
<match url="[A-Z]" ignoreCase="false" />
<action type="Redirect" url="{ToLower:{URL}}" />
</rule>
</rules>
</rewrite>
Global.asax
protected void Application_Start(object sender, EventArgs e)
{
//...
BuildStaticRoutes(RouteTable.Routes);
//...
}
public void BuildStaticRoutes(RouteCollection routes)
{
//...
routes.MapPageRoute("ROUTE-HOME", "home", "~/Home.aspx");
//...
}

If you are using IIS v7.5 you can add this in web.config
<system.webServer>
<rewrite>
<rules>
<rule name="HOMETOSEO" stopProcessing="true">
<match url="^Home" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="Home.aspx" />
</rule>
</rules>
</rewrite>
</system.webServer>
When you type http://mysite.com/Home, it will display http://mysite.com/Home.aspx. Is that what you are after or the other way around?

You can do it using a custom route by inheriting from RouteBase - so in your case it would look something like this
public class HomeRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
if (httpContext.Request.Url.ToString().ToLower().Contains("home.aspx"))
{
httpContext.Response.Status = "301 Moved Permanently"; //Optional 301 redirect
httpContext.Response.RedirectLocation = "Home";
httpContext.Response.End();
}
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
And then in you register routes you would have
routes.Add("HomeUrl", new HomeRoute());
So that any request to /Home.aspx would automatically redirect to /Home - obviously with a bit of extra work you could make this a bit more generic for any .aspx request.

Related

Modify and redirect for not found URl in web api

I enabled Html5 mode in angular for my project witch convert my URl from
A: qwe.com/#/products
to
B: qwe.com/products
But the problem is in this case if user trying to directly go to B, server (web api) catch the Url and return not found error so I need a way to catch all not found in server add a # sign to that and redirect to new Url but how should I do it?
Update:
Thanks to #Travis Collins
In Global.asax
private const string ROOT_DOCUMENT = "/index.html";
protected void Application_BeginRequest( Object sender, EventArgs e )
{
string url = Request.Url.LocalPath;
if ( !System.IO.File.Exists( Context.Server.MapPath( url ) ) )
Context.RewritePath( ROOT_DOCUMENT );
}
You need to do the rewrite on your server end for this. This will make the web server still serve your index.html file even when a request comes in for /products or anything else. In IIS for example, you would do this in web.config:
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
Lots of other servers are explained here:
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode

asp.net mvc hosting angular app with html5mode and routing

Alright, so I am hosting an angularjs inside asp.net mvc 5 and are using the html5mode(true) in my angular app to get rid of all hash signs in the url.
Everything works great, however, with my current setup that looks like this:
RouteConfig.cs:
routes.MapRoute(
name: "Default",
url: "app/{angular}",
defaults: new { controller = "Ng", action = "Index", angular= UrlParameter.Optional }
);
So that when I navigate to http://url/app/myangularroute my Ng/Index action returns the view which contains the ng-view container and the angular app is now active and working with the route provided
Now, my problem here is, when I navigate to http://url/app/ it returns a dir listning not allowed error which I cannot understand. Shouldn't my index action be returned as the angular parameter is set to optional?
And can I somehow avoid the "app" completely and still get my angular app to work? I have tried some rewrite rules but that gives me alot of errors because I am making use of the mvc bundling and minification functionality.
I could live with the url being the format it currently is but without the need to provide the optional parameter, like http://url/app/
Also, it's only an angular app, no other mvc view than the index.cshtml wrapper.
This guy seems to get it to work, but I can't see his mvc routes
Try adding this in your web.config sytem.webserver settings.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<system.webServer>
EDIT:
Try changing your RouteConfig.cs, like this:
routes.MapRoute(
name: "Default",
url: "app/{*.}",
defaults: new { controller = "Ng", action = "Index" }
);
EDIT2:
I had completely forgoten about this question, but now I just realized that maybe the problem is that you haven't configured your IIS Server to work with Html5Mode, have a look at this: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode
Concretelly this part:
Azure IIS Rewrites:
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
I hope that this helps.
This is my solution. I am using ASP.NET MVC + Web API.
ASP.NET MVC always returns the same HTML page for any URL, so AngularJS can take over in $locationProvider.html5Mode(true);
RouteConfig.cs
routes.MapRoute(
name: "Default",
url: "{*anything}",
defaults: new
{
controller = "Home",
action = "Index",
}
);
WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}/{id1}",
defaults: new
{
action = RouteParameter.Optional,
id = RouteParameter.Optional,
id1 = RouteParameter.Optional,
}
);
HomeController.cs
public ActionResult Index()
{
return File("~/index.html", "text/html");
}
Alright, I got it to work.
By doing this:
Remove the "app" route completely, and use the standard route.
Add the rewrite rule
Remove the base href from the layout
Ohh wow, I turned off the bundling and minification, that was actually what made it work in the end. When I turn it on I get an angular error.
I honestly thought I tried this like 10 times without success. It started to show signs of working when I removed the base href.
Old question but still valid, this is my solution :
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*"/>
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<!--for local dev enviroment-->
<add input="{REQUEST_URI}" pattern="^/(__browserLink)" negate="true" />
<!--if the url does not match a valid file we don't want it to be redirected to the index page-->
<add input="{REQUEST_URI}" pattern="\.(png|jpg|gif|css|js|html)$" negate="true" />
<!--web api route-->
<add input="{REQUEST_URI}" pattern="^/api/" negate="true" />
<!--ASP.NET Web API Help Page-->
<add input="{REQUEST_URI}" pattern="^/Help" negate="true" />
<!--Swagger-->
<add input="{REQUEST_URI}" pattern="^/apimap" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
With my ASP.NET 5 RC site - has WebAPI but not MVC - the solution was to up a default rewrite rule in wwwroot\web.config's system.webserver tag:
<rewrite>
<rules>
<clear />
<rule name="API" stopProcessing="true">
<match url="^(api)(.*)$" />
<action type="None" />
</rule>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
I am facing the same problem, i have set the base href in layout.cshtml ,put the webconfig rewrite rule, when loading the app,In bundle config i have set the all the scripts and css when launch the app ,its not get loaded . unexpected syntax error < is displayed in console.
when i remove the rule and base href and location provider is false , it working fine .
Angular Js Strange issue Ui Router Html5mode enabled page refresh issue in mvc 500 error

IIS 7 Rewrite web.config serverVariables directive not working in sub folder

I have the following code in my web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="IP Correction">
<match url="(.*)" />
<serverVariables>
<set name="REMOTE_ADDR" value="{HTTP_X-Forwarded-For}"/>
</serverVariables>
<action type="None" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
This works perfectly on the root of my site, however, the rule isn't being triggered in any of the sub folders.
I figured this out. The problem was in this line of code
<action type="None" />
You have to specify the rewrite action
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="IP Correction">
<match url="(.*)" ignoreCase="true" />
<serverVariables>
<set name="REMOTE_ADDR" value="{HTTP_X-Forwarded-For}" replace="true"/>
</serverVariables>
<action type="Rewrite" url="{R:0}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I faced a similar issue and created an IHttpModule to address it, which you can find here. URL Rewrite seems to have a bug where it won't execute on default document requests. The module doesn't have that issue. To implement it on your site, you'd add it to the <modules> section of your web.config, or if you want it to run server-wide, to your applicationHost.config.
The relevant bit of code is that you're hooking into HttpApplication's BeginRequest event, and running:
void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
string headervalue = app.Context.Request.Headers["X-Forwarded-For"];
if (headervalue != null)
{
Match m = REGEX_FIRST_IP.Match(headervalue);
if (m.Success)
{
app.Context.Request.ServerVariables["REMOTE_ADDR"] = m.Groups[1].Value;
app.Context.Request.ServerVariables["REMOTE_HOST"] = m.Groups[1].Value;
}
}
}
The Regex is ^\s*(\d+\.\d+\.\d+\.\d+). Full code at the gist.
If you compiled this code into a class library called HttpModules and put it in your GAC, you could then add this to your <modules> section, something like:
<add name="ClientIP" type="YourLibrary.ClientIP, YourLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=00DEADBEEF00" />

ASP.NET site. Redirect whole domain from http to https

Just like in a title. How to redirect whole domain for example: http://testdomain.com.au/ to https://testdomain.com.au/ Can i do it in IIRF file ? If yes how this should look like ? How to bind IIRF file to site ?
You can do this via an IIS Rewrite module:
http://www.iis.net/downloads/microsoft/url-rewrite
http://www.iis-aid.com/articles/how_to_guides/redirect_http_to_https_iis_7
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
Or you can redirect via the Global.asax file:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if ( !Request.IsSecureConnection)
{
string path = string.Format("https{0}", Request.Url.AbsoluteUri.Substring(4));
Response.Redirect(path);
}
}
http://forums.asp.net/t/1340392.aspx

Is it possible to call the IIS 7+ setUrl API from a managed HttpModule?

What I basically need is to manage a large set of URL rewrites and redirects. The redirects are easy to do but the rewrites should be proxyed through the ARR proxy in IIS. As far as I can tell the IIS rewrite module uses the native setUrl API in IIS to get the ARR proxy to forward the request. I'm not up to the task of writing a native module so I thought it might be possible to write a managed module to do the same.
#CarlosAg: Just to expand my comment on your answer. Heres the rules and providers I need to set up to make the rewrite module do what I want. Is it just me or doesn't it seem a little like manipulating the rewrite module into doing something it wasn't supposed to do?
<rewrite>
<providers>
<provider name="CustomRewrite" type="MyRewriteProviders.RewriteProvider, MyRewriteProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e72501f8a0edfe78" />
<provider name="CustomRedirectTemporary" type="MyRewriteProviders.RedirectTemporaryProvider, MyRewriteProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e72501f8a0edfe78" />
<provider name="CustomRedirectPermanent" type="MyRewriteProviders.RedirectPermanentProvider, MyRewriteProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e72501f8a0edfe78" />
</providers>
<rules>
<clear />
<rule name="Set Http">
<match url="." />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<serverVariables>
<set name="RequestProtocol" value="http" />
</serverVariables>
<action type="None" />
</rule>
<rule name="Set Https">
<match url="." />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTPS}" pattern="ON" />
</conditions>
<serverVariables>
<set name="RequestProtocol" value="https" />
</serverVariables>
<action type="None" />
</rule>
<rule name="Custom Rewrite">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{CustomRewrite:{RequestProtocol}://{HTTP_HOST}/{URL}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}" logRewrittenUrl="true" />
</rule>
<rule name="Custom Redirect (Temporary)" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{CustomRedirectTemporary:{RequestProtocol}://{HTTP_HOST}/{URL}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" redirectType="Found" appendQueryString="false" />
</rule>
<rule name="Custom Redirect (Permanent)" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{CustomRedirectPermanent:{RequestProtocol}://{HTTP_HOST}/{URL}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" />
</rule>
</rules>
</rewrite>
And the provider's code:
using System;
using System.Collections.Generic;
using Microsoft.Web.Iis.Rewrite;
namespace MyRewriteProviders
{
public enum ActionType
{
Rewrite,
RedirectPermanent,
RedirectTemporary
}
public abstract class BaseProvider : IRewriteProvider
{
protected abstract ActionType Action { get; }
public void Initialize(IDictionary<string, string> settings, IRewriteContext rewriteContext) {}
public string Rewrite(string value)
{
return RewriteEngine.RewriteUri(value, ActionType.Rewrite);
}
}
public class RewriteProvider : BaseProvider
{
protected override ActionType Action
{
get { return ActionType.Rewrite; }
}
}
public class RedirectTemporaryProvider : BaseProvider
{
protected override ActionType Action
{
get { return ActionType.RedirectTemporary; }
}
}
public class RedirectPermanentProvider : BaseProvider
{
protected override ActionType Action
{
get { return ActionType.RedirectPermanent; }
}
}
public static class RewriteEngine
{
public static string RewriteUri(string uri, ActionType action)
{
// Not actual rule engine implementation... just to demonstrate what it would do.
var ub = new UriBuilder(uri);
// Simulate a match on a rewrite rule
if (string.Equals(ub.Host, "rewrite.com", StringComparison.InvariantCultureIgnoreCase) && action == ActionType.Rewrite)
{
ub.Host = "rewrite-rewritten.com";
return ub.ToString();
}
// Simulate a match on a temporary redirect rule
if (string.Equals(ub.Host, "redirect.com", StringComparison.InvariantCultureIgnoreCase) && action == ActionType.RedirectTemporary)
{
ub.Host = "redirect-rewritten.com";
return ub.ToString();
}
// No rules matched. This will make the condition in the rewrite rule not match.
return string.Empty;
}
}
}
Apart from that, you need to setup IIS to allow the custom server variable and you need to sign and register the providers in the gac... This seems just a little more complicated than simply to be able to manipulate the request url like you are from the native api.
Have you considered using the URL Rewrite extensibility instead? You can easily create a provider that can map anything, you can pass any information to it through the parameters (only one string, but you could concatenate any number of them with some separator), and then resolve whatever you need, whether is a partial string for the URL, or the entire URL for that matter.
See: http://learn.iis.net/page.aspx/804/developing-a-custom-rewrite-provider-for-url-rewrite-module/
I've ended up using the ManagedFusion rewriter. The main reason is that this module seems fairly extensible and it also sports a built-in proxy. Whether it performs or not, only time, and a couple of tests, will tell.

Resources