Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Big Rock: URL generation for pages #5921

Closed
6 tasks done
rynowak opened this issue Mar 8, 2017 · 5 comments
Closed
6 tasks done

Big Rock: URL generation for pages #5921

rynowak opened this issue Mar 8, 2017 · 5 comments

Comments

@rynowak
Copy link
Member

rynowak commented Mar 8, 2017

Related Issues:


I have a proposal after spending some time with this. It feels very complimentary to what we have elsewhere in the system.

I know that this proposal can work because it's just a small twist on what we already have implemented. Doing something as simple as what's proposed here is beneficial because it doesn't require a lookup table or any custom logic for pages, it's just routing.

Proposal - Page Names

Conceptually, each page has a name that uniquely identifies it.

By default, the page name will be it's relative path based at the pages root directory, with unnecessary noise like the leading slash and file extension trimmed. This means that for a site with the root path of /Pages, then /Pages/Index.cshtml is Index, /Pages/Account/Signup.cshtml is Account/Signup and so on. Again, these are the defaults, and they are the way they are so that each page has an intuitive, typable name, and so that there are no collisions.

Overriding Page Names

You can customize a page name by giving a logical name either through application model, or as an additional token in the @page directive.

@page Directive

@page "{id}" "GetWidget"

Application Model

.AddRazorPagesOptions(options => options.SetPageName("/Account/Login", "Login"))

Generating URL UX

Now for the fun stuff. This just works.

Tag Helpers

<a asp-route-page="GetWidget" asp-route-id="17">...</a>

HTML Helpers

@Html.RouteLink(new { page = "GetWidget", id = 17 }) { ... }

IUrlHelper

@Url.Route(new { page = "GetWidget", id = 17 });

This is all just basic routing using the existing APIs. We can make it a lot nicer by adding some convenience APIs.

Tag Helpers

<a asp-page="GetWidget" asp-route-id="17">...</a>

HTML Helpers

@Html.PageLink("GetWidget", new { id = 17 }) { ... }

IUrlHelper

@Url.Page("GetWidget", new { id = 17 });

What I like about it

I like this model because there's no ceremony if you want to just do the default, but you can give a logical name to the things that you commonly deep link to.

I like this because it gets you out of concatenating things manually which is a huge pain.


I think the most obvious reaction is to look at a mapping like /Pages/Account/SignUp.cshtml -> Account/SignUp and say something like

😲 That's it? That doesn't abstract away the URL.

Yeah. That's it. Pages is low ceremony, what's simpler than files on disk and URLs in a hierarchy?

I think that 80% of the value that our URL generation system provides is in how we're able to parameter substitution in the URL and dynamically build the query string. Basically getting you out of the concatenation game.

For the other 20% think about defining a logical name for your pages that support deep linking. If it's worth it, it's worth it. I had some similar thought here this week so it's in my brain right now. For someone looking to abstract away the physical URL from the logical unit of a linking, we don't have a lot of tools right now. This is something that I think this proposal actually does better than controllers with conventional routing, and about the same as controllers with attribute routing.

@rynowak
Copy link
Member Author

rynowak commented Mar 8, 2017

/cc @DamianEdwards @Eilon @davidfowl

@rynowak rynowak added this to the Discussions milestone Mar 8, 2017
@rynowak rynowak self-assigned this Mar 8, 2017
@rynowak
Copy link
Member Author

rynowak commented Mar 8, 2017

Appendix A: Additional Convenience Methods

We might also want to consider an additional set of convenience methods for when you want to link to a sibling. This makes it easier to rename a folder without breaking the world.

Names intentionally awful

Imagine you want to link from /Pages/Blog/Index.cshtml to /Pages/Blog/Edit.cshtml?id=17

Tag Helpers

<a asp-page-sibling="Edit" asp-route-id="17">...</a>

HTML Helpers

@Html.PageSiblingLink("Edit", new { id = 17 }) { ... }

IUrlHelper

@Url.PageSibling("Edit", new { id = 17 });

This isn't a new routing system, it's just transformations on a string. The page name of the current page is Blog/Index. These apis would pull that out of route data and then generate a link using the page name Blog/Edit by removing the last segment and concatenating Edit.

@DamianEdwards
Copy link
Member

I love all of this, and it's absolutely required. We can't ship without something like this, as URL generation is one of the most painful parts of linking and redirecting between pages. Let's do it.

@rynowak rynowak assigned pranavkm and unassigned rynowak Mar 22, 2017
@rynowak
Copy link
Member Author

rynowak commented Mar 22, 2017

@pranavkm - please start on this after we resolve all of the tooling/VSIX/build/signing, Let's ignore everything in Appendix A for now

@pranavkm
Copy link
Contributor

pranavkm commented Mar 29, 2017

By default, the page name will be it's relative path based at the pages root directory, with unnecessary noise like the leading slash and file extension trimmed.

Should we do that for the ViewEnginePath too? With this change, we'll have one way to refer to a page in Startup e.g. options.Authorize("/Pages/Admin/Home"), but an ever so slightly different way (sans leading slash) when using it in routing e.g. @Url.Route(new { page = "Pages/Admin/Home" }). I think it might be better to not have the leading slash in either.

pranavkm added a commit that referenced this issue Apr 10, 2017
pranavkm added a commit that referenced this issue Apr 19, 2017
@pranavkm pranavkm moved this from Working to Done in Razor Pages 2.0.0-preview1 Apr 25, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

No branches or pull requests

4 participants