Windows Server Redirect Issue - windows-services

I am dealing with some client's that use Windows servers and as such do not support .htaccess files. This is not a huge deal but, my concern is this:
I have a rule set up in my .htaccess file to redirect the non-www version of the site to the www version. This makes the URL's look nicer and prevents duplicate content being indexed.
However, there does not seem to be a simple way to do this on a Windows server. I have read through tutorials on setting up a web.config file but, my Windows server experience is very limited and many times I only have FTP access to the site (no server access).
Any ideas on a quick and fairly simple solution, that I could use?

Create web.config (in the root directory) file with the next content:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<rewrite>
<rules>
<rule name="CanonicalHostNameRule" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.domain\.com$" negate="true" />
</conditions>
<action type="Redirect" url="http://www.domain.com/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
The URL Rewrite Module (at least version 2.0) has to be installed.

To use custom module create file CanonicalRedirectModule.cs in folder App_Code it the root folder of the Web Site Application with next content:
using System;
using System.Web;
public class CanonicalRedirectModule : IHttpModule
{
public const string configKeyCanonicalHostName = "CanonicalHostName";
private string configCanonicalHostName;
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
this.configCanonicalHostName = System.Configuration.ConfigurationManager.AppSettings[configKeyCanonicalHostName];
if (string.IsNullOrEmpty(this.configCanonicalHostName))
{
System.Diagnostics.Trace.TraceWarning("Can't find application setting {0} in configuration file (/configuration/appSettings/add/...).", configKeyCanonicalHostName);
//#if !DEBUG
// return;
//#endif
}
context.BeginRequest += new EventHandler(context_BeginRequest);
}
#endregion
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
if (app.Request.Url.Host != this.configCanonicalHostName) //&& !app.Request.IsLocal
{
UriBuilder newUrl = new UriBuilder(app.Request.Url);
newUrl.Host = this.configCanonicalHostName;
app.Response.Redirect(newUrl.ToString(), true);
}
}
}
Then configure module in web.config:
<?xml version="1.0"?>
<system.web>
<!-- Configuration for classic pipeline mode -->
<httpModules>
<add name="CanonicalRedirectModule" type="CanonicalRedirectModule"/>
</httpModules>
</system.web>
<system.webServer>
<!-- Configuration for integrated pipeline mode -->
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" >
<add name="CanonicalRedirectModule" type="CanonicalRedirectModule"/>
</modules>
</system.webServer>

Related

Web application developed in VS 2010 SP1 solution not working in VS 2017

I have a Legacy web application which is working perfectly in VS 2010 with service pack 1. I am trying to migrate the same solution to VS 2017.When I open the solution in 2017 and try to run it is hitting the Application_Start there after it goes to Application_EndRequest, it is never hitting the Session_Start event.
The error I am getting the the Application_EndRequest is
Session state is not available in this context. at System.Web.HttpApplication.get_Session()
My web application is using MVC architecture.
I have tried to enable the session in webconfig but still no luck.
<system.web>
<pages enableSessionState="true" />
</system.web>
web page version using is
<add key="webpages:Version" value="2.0.0.0" />
Target framework is
<compilation debug="true" targetFramework="4.0">
Mvc version using is
<add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
Note 1 :I already went through most of the stack overflow questions related to this issue not nothing is solving my issue .
Update :
protected void Application_Start()
{
AutoMapperConfiguration.Configure();
AreaRegistration.RegisterAllAreas();
}
void Application_EndRequest(object sender, EventArgs e)
{
//no code inside application end request.
}
protected void Session_Start(Object sender, EventArgs e)
{
try
{
string sessionId = Session.SessionID;
bool dbcheck = CheckDBConnection();
}
catch (Exception ex)
{
//handle execption
}
}
Note 2: The session_start itself is not hitting and I am not at all assessing session in application_start. I have commented all code inside the application start but still the same issue is coming.
I have tried to open the same solution from VS 2015, Still the same behavior it is hitting the Application_End event, and the error in object sender is
Session = '((System.Web.HttpApplication)sender).Session' threw an exception of type 'System.Web.HttpException'
Can anyone help me to resolve the same ? Any help will be greatly appreciated.
Finally I found the solution. In my webconfig file there is a url redirection rule is defined that is what making the issue. It is working perfectly after commenting that
<rewrite>
<rules>
<rule name="Redirect to https" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="SeeOther" />
</rule>
</rules>
</rewrite>

How to remove/disable mywebsite.azurewebsites.net domain after adding custom domain?

I have created a website on Azure, and linked it with custom domain name(CNET).
Now, when I look at domains on website configuration on Azure panel I see both www.mywebsite.com , and default mywebsite.azurewebsites.net. Both of these domains work fine and I can access website using any of these.
How can I remove mywebsite.azurewebsites.net domain? Does having both of these domains affect SEO?
EDIT*
Thanks for answers, I am trying to enable a 301 redirect, but it is not working. I have added this to web.config file ("example" being my actual site name)
<system.webServer>
<rewrite>
<rules>
<rule name="SEOAzureRewrite" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^example.azurewebsites.net$" />
</conditions>
<action type="Redirect" url="http://www.example.com/{R:0}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
I run the website but nothing happens. I can still access the mysite.azurewebsites.net address.
there is no problem in having both domains pointing to your website.
for SEO, you must do 301 redirect from mywebsite.azurewebsites.net to www.mywebsite.com.
It has to be 301 redirect. As this will tell the search engines to always index www.mywebsite.com
Since I couldn't set up the url rewrite in web.config, I created global filter to check for azure url and display error if so. Here is the filter, and I added a new view in my error pages for this purpose that just says "Page doesn't exist" to avoid indexing by search engines. Think this will solve possible duplicate indexing issues.
public override void OnResultExecuting(ResultExecutingContext context)
{
if (context.RequestContext.HttpContext.Request.Url != null)
{
string path = context.RequestContext.HttpContext.Request.Url.AbsoluteUri;
if (path.ToLower().Contains("mywebsite.azurewebsites") && !path.ToLower().Contains("error/oldazuresubdomainredirect650"))
{
throw new HttpException(650, "Azure legacy");
}
}
}
You can create a url rewrite rule to do exactly that
You just need to add a redirect rule to your site’s web.config file. You can do that by adding the following rewrite rule to the web.config file in your wwwroot folder. If you don’t have a web.config file, then you can create one and just paste the text below into it, just change the host names to match your site’s host names:
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect rquests to default azure websites domain" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^yoursite\.azurewebsites\.net$" />
</conditions>
<action type="Redirect" url="http://www.yoursite.com/{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
The above is all you need to do to get it to work. If you'd like to better understand what exactly that code does and why it works, there's a detailed writeup at https://zainrizvi.io/blog/block-default-azure-websites-domain/

How to add route to dynamic robots.txt in ASP.NET MVC?

I have a robots.txt that is not static but generated dynamically. My problem is creating a route from root/robots.txt to my controller action.
This works:
routes.MapRoute(
name: "Robots",
url: "robots",
defaults: new { controller = "Home", action = "Robots" });
This doesn't work:
routes.MapRoute(
name: "Robots",
url: "robots.txt", /* this is the only thing I've changed */
defaults: new { controller = "Home", action = "Robots" });
The ".txt" causes ASP to barf apparently
You need to add the following to your web.config file to allow the route with a file extension to execute.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- ...Omitted -->
<system.webServer>
<!-- ...Omitted -->
<handlers>
<!-- ...Omitted -->
<add name="RobotsText"
path="robots.txt"
verb="GET"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
</configuration>
See my blog post on Dynamically Generating Robots.txt Using ASP.NET MVC for more details.
Answer here: url with extension not getting handled by routing. Basically, when asp sees the "." it calls the static file handler, so the dynamic route is never used. The web.config files needs to be modified so /robots.txt will not be intercepted by the static file handler.
Muhammad Rehan Saeed's System.Web.Handlers.TransferRequestHandler approach in web.config approach did not work for me due to the environment I was working in, resulting in 500 errors.
An alternative of using a web.config url rewrite rule worked for me instead:
<rewrite>
<rules>
<rule name="Dynamic robots.txt" stopProcessing="true">
<match url="robots.txt" />
<action type="Rewrite" url="/DynamicFiles/RobotsTxt" />
</rule>
</rules>
</rewrite>

ApiController returns 404 when ID contains period

I have an ApiController and I want to use email addresses as the ID parameter for requests:
// GET api/employees/email#address.com
public CompactEmployee Get(string id) {
var email = id;
return GetEmployeeByEmail(email);
}
However, I cannot get this to work (returns 404):
http://localhost:1080/api/employees/employee#company.com
The following all work:
http://localhost:1080/api/employees/employee#company
http://localhost:1080/api/employees/employee#company.
http://localhost:1080/api/employees?id=employee#company.com
I have set relaxedUrlToFileSystemMapping="true" in my web.config as detailed by Phil Haack.
I would very much love the full email address to work, but any time the period is followed by any other character, the request returns a 404. Any help would be greatly appreciated!
Solution
Due to a lack of other options, I've headed in the direction Maggie suggested and used the answer from this question to create a rewrite rule to automatically append a trailing slash when I need an email in the URL.
<system.webServer>
....
<rewrite>
<rules>
<rule name="Add trailing slash" stopProcessing="true">
<match url="^(api/employees/.*\.[a-z]{2,4})$" />
<action type="Rewrite" url="{R:1}/" />
</rule>
</rules>
</rewrite>
</system.webServer>
Would adding a trailing slash work for your scenario?
http://localhost:33021/api/employees/employee#company.com/
Check your IIS settings:
Home Directory -> Configuration
Edit the .aspx application extension and ensure that the setting Verify that file exists is off.
UPDATE
I've just tested with a default MVC4 Web API project
URL: http://localhost:10983/api/values/cool#email.com
Action in ValuesController:
public string Get(string id)
{
return id;
}
This was the response:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">cool#email.com</string>
This is what worked for me:
I was running on targetFramework = 4.6.1. I have upgraded to 4.6.2 and added this in web.config:
<system.web>
<customErrors mode="Off"/>
<compilation debug="true" targetFramework="4.6.2"/>
<!-- This will allow to search for stuff that contains . & etc.-->
<httpRuntime targetFramework="4.6.2" maxRequestLength="100000" maxUrlLength="2048" relaxedUrlToFileSystemMapping="true" requestPathInvalidCharacters=""/>
</system.web>
The requestPathInvalidCharacters="" is to be able to have stuff like & etc in URI, in encoded form, of course.

How to redirect HTTP to HTTPS in MVC application (IIS7.5)

I need to redirect my HTTP site to HTTPS, have added below rule but I am getting 403 Error when tried using http://www.example.com, it works fine when I type https://www.example.com in browser.
<system.webServer>
<rewrite>
<rules>
<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>
</rules>
</rewrite>
</system.webServer>
You can do it in code:
Global.asax.cs
protected void Application_BeginRequest(){
if (!Context.Request.IsSecureConnection)
Response.Redirect(Context.Request.Url.ToString().Replace("http:", "https:"));
}
Or You could add the same code to an action filter:
public class SSLFilter : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext){
if (!filterContext.HttpContext.Request.IsSecureConnection){
var url = filterContext.HttpContext.Request.Url.ToString().Replace("http:", "https:");
filterContext.Result = new RedirectResult(url);
}
}
}
In the Global.asax.cs:
Simple redirect
protected void Application_BeginRequest()
{
if (!Context.Request.IsSecureConnection
&& !Context.Request.IsLocal // to avoid switching to https when local testing
)
{
// Only insert an "s" to the "http:", and avoid replacing wrongly http: in the url parameters
Response.Redirect(Context.Request.Url.ToString().Insert(4, "s"));
}
}
301 redirect: SEO best practice (Search Engine Optimization)
The 301 Moved Permanently redirect status response code is considered a best practice for upgrading users from HTTP to HTTPS (see Google recommendations).
So if Google or Bing robots will be redirected too, consider this:
protected void Application_BeginRequest()
{
if (!Context.Request.IsSecureConnection
&& !Context.Request.IsLocal // to avoid switching to https when local testing
)
{
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", Context.Request.Url.ToString().Insert(4, "s"));
Response.End();
}
}
I use the following in Global.asax:
protected void Application_BeginRequest()
{
if (FormsAuthentication.RequireSSL && !Request.IsSecureConnection)
{
Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://"));
}
}
I have the following ASP.NET MVC rewrite rule in Web.config file:
You can try this code with web.config file. If your URL is http://www.example.com then it will be redirect to this URL https://www.example.com.
<system.webServer>
<rewrite>
<rules>
<rule name="http to https" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
You could use the RequireHttpsAttribute for simple cases.
[RequireHttps]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
As stated in MSDN...
"Represents an attribute that forces an unsecured HTTP request to be
re-sent over HTTPS."
RequireHttpsAttribute
I'm not sure you'd want to use this to enforce HTTPS across a large site though. Lots of decorating to do, and opportunity to miss controllers.
It's very simple. Just add one line in "Global.asax" file as below:
protected void Application_Start()
{
GlobalFilters.Filters.Add(new RequireHttpsAttribute(true));
}
If you would like to apply only server-side, not local side then apply following code:
protected void Application_Start()
{
if (!HttpContext.Current.Request.IsLocal)
GlobalFilters.Filters.Add(new RequireHttpsAttribute(true));
}
Hope it will help you :) Thank you!
Use this code in web.config file for redirect http:// to https://
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTPS force" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer></configuration>
I did it thusly, since a local debug session uses custom port numbers:
protected void Application_BeginRequest()
{
if (!Context.Request.IsSecureConnection)
{
if (HttpContext.Current.Request.IsLocal)
{
Response.Redirect(Context.Request.Url.ToString().Replace("http://localhost:25885/", "https://localhost:44300/"));
}
else
{
Response.Redirect(Context.Request.Url.ToString().Replace("http://", "https://"));
}
}
}
Preferably there would be some way to get the URL and SSL URL programmatically...
To force https only when the website is lunched on the server and ignore it while running the website on your machine for development :
In Global.asax :
You'll need the Application_BeginRequest() method
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// .....
}
//force https on server, ignore it on local machine
protected void Application_BeginRequest()
{
if (!Context.Request.IsSecureConnection && !Context.Request.Url.ToString().Contains("localhost"))
Response.Redirect(Context.Request.Url.ToString().Replace("http:", "https:"));
}
}
This answer is not exactly for OP but for those who could not make it work like me and have come across this (and although I know there is 403 not 404 error in OP), please refer to this answer if you are getting 404 instead: https://stackoverflow.com/a/6962829/5416602
Please check that you have binding for HTTP port (80) and not only HTTPS port (443) in your IIS
I'm unable to add comments, but thought this supplementary info would maybe help somebody.
I implemented the Global.asax idea with the 301 Permanent Redirect, and added http binding to the site in IIS. It still gave me 403 Forbidden until I remembered to untick "Require SSL" in SSL Settings.

Resources