dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.2k stars 9.95k forks source link

Blazor-server-side Multi routing such as in mvc #37485

Closed Alerinos closed 10 months ago

Alerinos commented 2 years ago

I have two sides

@page "/{article?}"

<h2>@article</h2>

@code {
    [Parameter]
    public string article { get; set; } = "";

    protected override async Task OnInitializedAsync() 
    {
        if(article != "testArticle")
        {
            // return NOTFOUND
        }
    }

}
@page "/{game?}"

<h2>@game</h2>

@code {
    [Parameter]
    public string game { get; set; } = "";

    protected override async Task OnInitializedAsync() 
    {
        if(game != "testGame")
        {
            // NOTFOUND
        }
    }

}

I would like many sites to be able to run under one domain like in mvc example:

domain.com/good-news
dmoain.com/best-game
domain.com/good-forwarding
domain.com/testGame
domain.com/testArticle

in mvc it was enough to give return NotFound();

javiercn commented 2 years ago

@Alerinos thanks for contacting us.

This is already possible today provided that you host your apps in different base paths. Here is a sample I wrote a while ago that you can use as a starting point. It's for Blazor webassembly, however you should be able to adapt it for Blazor server without much trouble.

Alerinos commented 2 years ago

I didn't really mean it. The application is shared, but large sites have several sections. For example, a sports website may have articles, players and sports clubs. Instead of doing

domain.com/club/Manchester-United -> domain.com/Manchester-United
domain.com/footballer/ronaldo ->domain.com/ronaldo
domain.com/article/best-match-ever-2020 -> domain.com/best-match-ever-2020

@javiercn I don't think your example will work that well

javiercn commented 2 years ago

@Alerinos it's not clear to us what you are trying to achieve.

Are you looking for something similar to Areas in MVC?

Alerinos commented 2 years ago

@javiercn I am looking for a way for many pages to have a common dynamic link. Articles, clubs, footballers, coaches, stadiums. I want to do short links for SEO. Instead of creating a link with the module name, it's all directly from the database. When entering the page, one query flies, if it finds it, it returns the result, if not, it continues with the query. If you find something in the database, this page is displayed.

ghost commented 2 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

enetstudio commented 2 years ago

@Alerinos, I believe that the Router's OnNavigateAsync feature can solve your issue.

Here's a simple code sample, checking the url path and navigating to the required url. This fulfills what you requested at the start of your question. I believe you can create a well-grained and complex navigation scheme. You can also query your database through Web Api end points, etc. See here the docs and follow the explanations:

App.razor


@inject NavigationManager NavigationManager

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true" OnNavigateAsync="@OnNavigateAsync">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>
@code {

    private async Task OnNavigateAsync(NavigationContext context)
    {
        if (context.Path.ToLower() == "testArticle".ToLower())
        {
            NavigationManager.NavigateTo("counter");
        }
        else if (context.Path.ToLower() == "testGame".ToLower())
        {
            NavigationManager.NavigateTo("fetchdata");
        }

        await Task.CompletedTask;
    }
}```

Index.razor
------------

    page "/{MyParam?}"

    @code 
    {
         [Parameter]
        public string MyParam { get; set; } = "";
    }

I do hope that's what you were after. It seems to me that you may also  need to use the pattern suggested by javiercn above.
Alerinos commented 2 years ago

@enetstudio Unfortunately that won't work, it will only create a redirect. For this to work, you need to use the RenderHandle and the Render function

@pranavkm @javiercn Maybe it's worth taking a look at a custom router in .net 7? It is very useful.

Alerinos commented 2 years ago

Example:

app.UseEndpoints("/{name}",endpoints =>
{
    endpoints.MapControllerRoute(() => {
    if(db.ToDo.Any(x => x.Name == endpoints.name))
       RenderHandle.Redner(Pages.Counter)
    }
    );  

    endpoints.MapControllerRoute(() => {
    if(db.Weather.Any(x => x.ShortName == endpoints.name))
       RenderHandle.Redner(Pages.Fetchdata)
    }
    );        

  // OR
      endpoints.MapControllerRoute(() => {
    if(db.Weather.Any(x => x.ShortName == endpoints.name))
       RenderHandle.Redner(Pages.Fetchdata, endpoints.name) // Add One Get parameteres 
    }
    );        
}
);

Database:

ToDo
ID | Name
1 | oldToDo
2 | newToDo

Weather
ID | ShortName
1 | UK
2 | USA

If we type domain.com/usa This will show us the page Pages.Fetchdata or domain.com/newToDo use page Pages.Counter

Alerinos commented 2 years ago

Recently, I brought up this topic here https://github.com/dotnet/aspnetcore/issues/39719

mkArtakMSFT commented 10 months ago

Hi. Thanks for contacting us. We're closing this issue as there was not much community interest in this ask for quite a while now. You can learn more about our triage process and how we handle issues by reading our Triage Process writeup.