Bhuban Shrestha
Bhuban Shrestha

Reputation: 1324

Redirect to dynamically added URL in MVC 5

My requirement is to redirect user to new url from old url . My entity is as follows:

public class HttpRedirect
{
    [Key]
    public int Id { get; set; }

    [Required(ErrorMessage = "Old url is required.")]
    [MaxLength(1000)]
    //[Url]
    [Display(Name = "Old Url")]
    public string OldUrl { get; set; }


    [Required(ErrorMessage = "New url is required.")]
    [MaxLength(1000)]
    //[Url]
    [Display (Name = "New Url")]
    public string NewUrl { get; set; }

}

Url is commented so that I can work in localhost.

So when Old url is requested I want the request is transferred to new url To achieve this in global.asax file in Application_BeginRequest event I have following code

protected void Application_BeginRequest(object sender, EventArgs e)
{
  //You don't want to redirect on posts, or images/css/js
  bool isGet = HttpContext.Current.Request.RequestType.ToLowerInvariant().Contains("get");
  if (isGet && HttpContext.Current.Request.Url.AbsolutePath.Contains(".") == false)
  {
    string lowercaseURL = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
    string newUrl = new HttpRedirectRepository().RedirectUrl(lowercaseURL);
    if(newUrl != null)
       {
         lowercaseURL = newUrl;
       }
     lowercaseURL = lowercaseURL.ToLower().Trim() + HttpContext.Current.Request.Url.Query;
     Response.Clear();
     Response.Status = "301 Moved Permanently";
     Response.AddHeader("Location", lowercaseURL);
     Response.End();
   }
}

I have implemented the above code to accomplish 2 task. 1. Change url to lower case 2. If new url is available for requested url redirect to that url.

With my above implementation I have strong feeling that its working but causing infinite loop by redirecting to a lowercaseURL

So how can I prevent multiple redirection. For e.g. I request http://localhost:80/mypage and I have set its new url to http://localhost:80/home then when mypage is requested it should redirect to home making url in lowercase and redirect should occur only one time.

note

  1. I need to redirect within my own domain only.
  2. User will enter full url address for both old and new url.

UPDATE

With some hint from @RobertHarvey I have modified my code as follows which is working for me

protected void Application_BeginRequest(object sender, EventArgs e)
{
  //You don't want to redirect on posts, or images/css/js
  bool isGet = HttpContext.Current.Request.RequestType.ToLowerInvariant().Contains("get");
  if (isGet && HttpContext.Current.Request.Url.AbsolutePath.Contains(".") == false)
  {
    bool redirect = false;
    string requestUrl = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
    //You don't want to change casing on query strings
    string newUrl = new HttpRedirectRepository().RedirectUrl(requestUrl);
    if (newUrl != null)
    {
      requestUrl = newUrl;
      redirect = true;
     }
     if (Regex.IsMatch(requestUrl, @"[A-Z]"))
     {
       requestUrl = requestUrl.ToLower().Trim() + HttpContext.Current.Request.Url.Query;
       redirect = true;
      }
      if (redirect)
      {
        Response.Clear();
        Response.Status = "301 Moved Permanently";
        Response.AddHeader("Location", requestUrl);
        Response.End();
       }
    }
} 

Though still I believe updated implementation has some limitation. I would appreciate any further code enhancement and case coverage.

Upvotes: 0

Views: 1040

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239440

Your two "notes" are contradictory. If you only want to allow redirection within your domain, then recording a full URL, including a domain, is entirely unnecessary, and only serves to complicate things. Make the old/new URLs just absolute paths. This also solves your problem with working in development vs. production, since you don't need to worry about the data having the right domain for the right environment.

Note: your infinite redirect is a bug in your code here. You should be redirecting to newUrl, not lowercaseUrl. In the case where newUrl is null, there is no redirect, so you should simply not redirect at all in that case.

Upvotes: 0

Related Questions