Pretty URL ASP.NET MVC

2020-02-23 05:19发布

问题:

How can I get pretty urls like localhost:8888/News/Example-post instead of localhost:8888/Home/Details/2

My HomeController has the following for the Details method

public ActionResult Details(int id)
{
    var ArticleToView = (from m in _db.ArticleSet where m.storyId == id select m).First();

    return View(ArticleToView);

回答1:

As the ASP.NET routing system is somewhat complicated, there are many ways to accomplish what you describe.

First of all, do you just want to have a pretty URL for the Details method? If so, you might consider renaming HomeController to NewsController or moving the Details method into a new NewsController class - that will automatically form the /News part of the URL. If you don't want a /Details part, you might rename your Details method Index, as that will be automatically called by /News. Finally, you need to change your int id parameter into string name.

If you want many custom URLs, you're going to have to define your own routes. Here are two ways of doing this:

1. The easiest way I've found is to use an ASP.NET MVC Attribute-Based Route Mapper. That way, all you have to do is add an attribute on each method you want a pretty URL for and specify what URL you want.

First, you must follow a few steps to set up the attribute-based route mapping system, as outlined on that link. After completing those steps, you must change your method to look like this:

[Url("News/{name}")]
public ActionResult Details(string name)
{
    var ArticleToView = (from m in _db.ArticleSet where m.storyName == name select m).First();

    return View(ArticleToView);
}

2. Alternatively, you can define your custom routes manually in Global.asax.cs. In your RegisterRoutes method, you can add the following in the middle:

routes.MapRoute(
                "NewsDetails",                                                   
                "News/{name}",                                 
                new { controller = "News", action = "Details", name = "" }
            );


回答2:

What I do on my sites is that I check the URL against either the Page Title or Page Stub in cases where the page titles could have the same name for instance if you have a site that posts a "Picture of the Week" you may want to use a stub instead of title as you'll have multiples named the same thing.

URLs look like this: http://mySite.com/Page/Verse-of-the-Week

Global.asax contains this:

routes.MapRoute("Pages", "{controller}/{pageID}", new { controller = "Page", action = "Index", pageID = "Home" });

PageController is this:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Index(string pageID)
    {
        if (pageID == null)
        {
            pageID = pageRepository.HomeOrLowest();
        }
        var p = pageRepository.ByStub(pageID);
        if (p == null) { return RedirectToAction("NotFound", "Error"); }
        return View(p);
    }

The repository looks like this:

    private static Func<mvCmsContext, string, Page> _byStub =
        CompiledQuery.Compile((mvCmsContext context, string pageTitle) =>
            (from p in context.Pages
             where p.pageTitle.Replace(" ", "-") == pageTitle
             select p).SingleOrDefault());
    public Page ByStub(string pageTitle)
    {
        return _byStub(context, pageTitle);
    }

I hope that helps.

Edit to add duplicate handling:

    private static Func<mvCmsContext, string, int> _pageExists =
        CompiledQuery.Compile((mvCmsContext context, string pageTitle) =>
            (from p in context.Pages
             where p.pageTitle.Replace(" ", "-") == pageTitle
             select p).Count());
    public bool PageExists(string pageTitle)
    {
        return Convert.ToBoolean(_pageExists(context, pageTitle));
    }

Validates like this:

        IValidationErrors errors = new ValidationErrors();
        if (CreateOrEdit == "Create")
        {
            if (pageRepository.PageExists(model.pageTitle) && !String.IsNullOrEmpty(model.pageTitle))
                errors.Add("pageTitle", "A page with this title already exists.  Please edit it and try again.");
        }


回答3:

Please check out this package I've created: https://www.nuget.org/packages/LowercaseDashedRoute/ And read the one-line configuration here: https://github.com/AtaS/lowercase-dashed-route