1

I am developing a website which contains some tutorials using MVC4 and entity framework. All the tutorials will be saved in database and based on the Tutorial Id (say TId) provided in the requested URL it will retrieve all the information regarding that tutorial in the action method and render in the view and display to the user. A sample URL is mentioned below.

URL: www.mysite.com/Tutorials/Show/452

Where Tutorials is Controller Name and Show is the action method name.

Here 452 is the TId. So when this URL is requested tutorial with TId 452 will be displayed. But what I want is, I want to append the dashed tutorial name at the end as shown below.

www.mysite.com/Tutorials/Show/452/My-Test-Tutorial

I can replace the space with '-' and generate the string but I dint find a way to append it to the URL.

This works perfectly with stackoverflow site. For example, even though we request "In MVC4, how to redirect to a view from a controller action with parameters in the Url?" the question with Id "20035665" is getting displayed and URL will be changed to "In MVC4, how to redirect to a view from a controller action with parameters in the Url?".

Can anyone pls help me on this?

5
  • Tutorials is the name of the controller, right? Commented Aug 8, 2014 at 7:15
  • Can I ask why you want to append name in URL which makes url lengthy? With Tid, server will know tutorial name anyway. Second even if you have strong reason to pass tutorial name, there are other ways to send data to server. Commented Aug 8, 2014 at 7:56
  • @Stefan Baiu.. Yes. Tutorials is the controller name and Show is the action method name. Commented Aug 8, 2014 at 8:22
  • @SBirthare.. Am not including title in the url for passing input data to server but to make the url look friendly. Just by having a look at the URL we should be able to know the title. Commented Aug 8, 2014 at 8:29
  • @kewlcoder: This also improves SEO, I'm using the method I have mentioned in my answer in my sites. Commented Aug 8, 2014 at 9:23

2 Answers 2

3

Assuming I understood your problem correctly, here's the solution I propose:

Add the following change to your routing mechanism:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Tutorials",
            url: "Tutorials/{id}/{title}",
            defaults: new { controller = "Tutorials", action = "Show", title = UrlParameter.Optional },
            constraints: new { id = @"\d+" }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

and then in your Tutorials controller:

public class TutorialsController : Controller
{
    // GET: /Tutorials

    public ActionResult Index()
    {
        // here you can display a list of the most recent tutorials or whatever
        return View();
    }

    // GET: /Tutorials/1 (will be redirected to the one below)
    // GET: /Tutorials/1/Intro-into-ASP_NET-MVC

    public ActionResult Show(int id, string title)
    {
        string key = string.Format("tutorial-{0}", id.ToString());
        Tutorial model = TempData[key] as Tutorial;

        // if this is not a redirect
        if ( model == null )
        {
            model = GetTutorial(id);
        }

        // sanitize title parameter
        string urlParam = model.Title.Replace(' ', '-');
        // apparently IIS assumes that you are requesting a resource if your url contains '.'
        urlParam = urlParam.Replace('.', '_');
        // encode special characters like '\', '/', '>', '<', '&', etc.
        urlParam = Url.Encode(urlParam);

        // this handles the case when title is null or simply wrong
        if ( !urlParam.Equals(title) )
        {
            TempData[key] = model;
            return RedirectToAction("Show", new { id = id, title = urlParam });
        }

        return View(model);
    }

    private Tutorial GetTutorial(int id)
    {
        // grab actual data from your database
        Tutorial tutorial = new Tutorial { Id = 1, Title = "Intro into ASP.NET MVC" };
        return tutorial;
    }
}

UPDATE:

the solution presented above will redirect
/Tutorials/1
to
/Tutorials/1/Intro-into-ASP_NET-MVC.

If you actually want to display the action name in the url, like /Tutorials/Show/1/Intro-into-ASP_NET-MVC you can just change the "url" in the "Tutorials" route to url: "Tutorials/Show/{id}/{title}".

You can also replace the RedirectToAction with RedirectToRoute("Default", new { id = id, title = urlParam }); which will make sure it matches the route named "Default", but this approach would yield the following url: www.mysite.com/Tutorials/Show/1?title=Intro-into-ASP_NET-MVC

Sign up to request clarification or add additional context in comments.

Comments

1

You can have a route config as below and when you create URLs you can pass tutorial title to a method which convert the given text to URL friendly text.

Example

In Route Config

routes.MapRoute(
    name: "Tutorials",
    url: "{controller}/{action}/{tid}/{title}",
    defaults: new { controller = "Tutorials", action = "Show", tid = UrlParameter.Optional, title = UrlParameter.Optional }
);

In a View when you create URLs

<a href='@Url.Action("Tutorials", "Show", new { tid = tutorial.ID, title = ToFriendlyUrl(tutorial.Title) })'>My Tutorial</a>

Then in Show method

public ActionResult Show(int tid, string title)
{
    // if the title is missing you can do a redirect inside action method

    return View();
}

1 Comment

The link to github is broken

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.