Search code examples
asp.net-mvcasp.net-mvc-3asp.net-routing

Redirect to another controller+ action without changing URL in ASP.Net MVC3


Note: Below is just a small demo sort to simulate what i am looking for:

Below are the urls format on my app that user can see

mydomain.com/cat/1  --display cat with id 1 |controller=Cat, action=DisplayDetails
mydomain.com/dog/2  --display dog with id 2 |controller=Dog, action=DisplayDetails
mydomain.com/cow/2 --display cow with id 3  |controller=Cow, action=DisplayDetails

I have maintained a system where no 2 animals(may be of different kind) can have same id, it means if there is a cat with id=1, we cant have any other animal with that id. Also from my system i can extract animal details+ type just from animal id

Apart from existing URL pattern, I am planning to create a short Url in format as below

mydomain.com/1  --this will show cat
mydomain.com/2  --this will show dog
mydomain.com/3  --this will show cow

Routes i have created are as below, and they appear same order in global.asax

pattern= Cat/{id}, controller= Cat, action=DisplayDetails
pattern= Dog/{id}, controller= Dog, action=DisplayDetails
pattern= Cow/{id}, controller= Cow, action=DisplayDetails
pattern= {id}, controller= DisplayAnyAnimal ----------i want help in this Route

Currently Controller looks like this

public class DisplayAnyAnimalContoller : Controller
{
      public ActionResult Index(string animalId)
      {
           //iam processing request here from animalId
           //now i know which contoller+action needs to be executed

          //say for instant i have to display dog with id=2

          //currently iam doing this to redirect and its working fine, 
          //but it changes url
          -----------------------------------------------
          #########################
          ### i need help here  ###       
          #########################
         return RedirectToRoute(new {contoller="Dog",action="DisplayDetails",id=2 });             
          -----------------------------------------------
      }
}

Now the problem with RedirectToRoute / RedirectToAction is they both changes the URL. But i dont want to change my url pattern.

Please suggest me how to achieve this, you may suggest some entirely different way, to achieve this


Solution

  • You could write a custom animal route:

    public class AnimalRoute : Route
    {
        public AnimalRoute(string url, IRouteHandler routeHandler)
            : base(url, routeHandler)
        { }
    
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            var rd = base.GetRouteData(httpContext);
            var id = rd.GetRequiredString("id");
    
            // TODO: Given the id decide which controller to choose:
            // you could query the database or whatever it is needed.
            // Basically that will be the code you had in the beginning
            // of the index action of your DisplayAnyAnimalContoller which
            // is no longer needed.
            if (id == "1")
            {
                rd.Values["controller"] = "Cat";
            }
            else if (id == "2")
            {
                rd.Values["controller"] = "Dog";
            }
            else if (id == "3")
            {
                rd.Values["controller"] = "Cow";
            }
            else
            {
                // no idea what this animal was
                throw new HttpException(404, "Not found");
            }
            rd.Values["action"] = "index";
            return rd;
        }
    }
    

    and then register it in Global.asax:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.Add(new AnimalRoute("{id}", new MvcRouteHandler()));
    }
    

    Now when you navigate to mydomain.com/1, the GetRouteData method of the custom route will be executed, will fetch the id=1, and then it will use the Index action of the Cat controller.