I'm converting my website from Web Forms to .NET Core. I don't want to change the directory level of various files, e.g.:
MYDOMAIN.com/FAQ.html
MYDOMAIN.com/Privacy.html
By using the UseStaticFiles() middleware, I can place these in the wwwroot folder and they will be served as is. However, I don't know how to apply a Layout page with my website theme to those files since they're outside of the MVC framework.
I'd like to leverage the Layout files and MVC framework by using .cshtml files, but I'm also trying to avoid the extra controller directory that's imposed on the URL:
MYDOMAIN.com/home/FAQ.html
MYDOMAIN.com/home/Privacy.html
Maybe this is short-sighted, but how do developers handle this?
And actually, my existing files are .aspx at the moment, not .html files so that adds another level of confusion as to what the convention is for migrating to .Net Core. Should I use any .aspx files anywhere in the project or should they all be converted to .cshtml / .html files? Or something else?
I have successfully implemented a solution, but it's kind of a hack. I add controllers for each static page, for example I created both a FAQController.cs and PrivacyController.cs.
Each controller has only Index() actions so that they can take advantage of _Layout.cshtml and _ViewStart.cshtml.
It seems like a roundabout way to go just to move the following up one level e.g.
MYDOMAIN.com/FAQ
MYDOMAIN.com/Privacy
but it works.
The "standard" Blazor WASM application is hosted inside a static HTML page; e.g., index.html. Due to certain requirements, I want to host Blazor inside a Razor pages application.
What I did is starting from a "standard" Blazor WASM application, removed the static files, because I do not need them, moved the content of index.html to the Wasm.cshtml, and change endpoints.MapFallbackToFile("index.html"); to endpoints.MapFallbackToPage("/Wasm");.
Everything seemed to be working as expected; I can run the application and navigate to the different pages I have in Blazor.
However, things fall apart when I try to access a page using its URL; e.g., http://mysite/counter, where /counter is a page in Blazor, and I get the following error:
An unhandled exception occurred while processing the request.
AmbiguousMatchException: The request matched multiple endpoints. Matches:
/Wasm
/Wasm
Can someone help me identify what I am doing wrong?
P.S.:
I looked at some answer here, but all that I found is people talking about Blazor Server.
I am using .NET 3.1 and Blazor 3.2.
I want to use my Razor Pages application to host/serve Blazor WASM not mixing them in a single project. They as still 2 different projects.
I am totally aware that Blazor WASM and Razor Pages are unrelated technologies. I am not trying to integrate them. I am only trying to server Blazor WASM files from a dynamic page. If it makes you think better about what I am trying to achieve, think about Razor Pages as any server-side technology; PHP, Node, or whatever, then apply this to the routing issue that I am trying to resolve.
OK, based on what you've written so far take a look at ShaunCurtis/Blazor-Experimental on Github. It's a temporary Repo for some experimental code. Ignore BlazorTest. The startup project is Blazor-Experimental.
The default page is a normal razor page. It's a mixed Razor, Blazor Server and Blazor WASM site. All the WASM routes look like wasm/fetchdata, so we have different URLs for all the Server and WASM "Pages".
Startup differentiates URLs using multiple endpoints, so any URL that is in the "scope" of the Blazor WASM application gets set to _wasm.cshtml. Anything else that can't be mapped directly is in the "scope" of the Blazor Server Application at _host.cshtml. All plan Razor pages on the site get served as is. You don't need the Blazor Server bit at all, just fallback to the default Razor page.
endpoints.MapFallbackToPage("/wasm/{**segment}", "/_wasm");
endpoints.MapFallbackToPage("/_Host");
To summarise the answer:
Create a Blazor WASM project. You can copy the one from Blazor Hosted template.
Reference the project from the Razor Pages project.
Create the page that will host Blazor WASM; e.g., Wasm.cshtml, and make sure the page route is not set; i.e., only #page at the top of the page, so that it takes the default route /wasm.
Copy the code from index.html in the Blazor WASM project into Wasm.cshtml.
Important: If you are using your own layout, it is important to have <base href="/" /> on the page or the layout <head> section.
Remove all the static files from form the Blazor WASM project; e.g., index.html.
Remove all *.razor pages from the Blazor WASM project.
Add Wasm.razor to the Blazor WASM project and set its route to /wasm; i.e., #page "/wasm".
In Startup.cs in the Razor Pages project, add app.UseBlazorFrameworkFiles(); after app.UseStaticFiles();.
Also in the same Startup.cs, add endpoints.MapFallbackToPage("/wasm/{**segment}", "/wasm"); inside app.UseEndpoints() lambda.
Now run the application and navigate to /wasm. You should see the content of your Wasm.razor in addition to whatever layout you have set. You will get the same result when you paste the URL http://whateveryoursiteis/wasm.
You give very little information, so I'll have to make a number of guesses.
I guess you based your WASM integration on the Blazor WASM ASP.NET hosted template. That template consists of three projects: The .Client project, the .Server project and some extra project with shared models (they're probably doing clean architecture). The server project is a Razor pages project and the client a WASM project.
What you must understand is that a Blazor WASM project is not comparable with a Razor pages application. A Blazor WASM, or actually any WASM file is a different kind of binary and is fully run at the client! It is a client-side application. I.e. the output binary is totally different. You cannot have one project that generates both a server (x86/arm) binary and a client (WASM) binary. You need two separate projects.
What actually happens while compiling the WASM project, is that all page routing is also converted to WASM. Just inspect your network traffic when you change a page. Even though you browser url changes, that's fake... there is no network traffic! In fact, you stay on the same page.
Now think what happens when you enter "[..]/counter" manually in the browser. The host will actually again download the same .wasm file from the root ("/" = "/Index") and then parse the routing client-side.
Going back to your problem. For some reason you copied all the contents from the Blazer WASM project wwwroot/index.html to a Razor Page project Pages/Index.cshtml. Now you're confusing the whole routing system. When you type "[...]/counter", the WASM router will tell you that the .wasm file needs to be downloaded from "/Index". At the same time the Razor Pages router will tell you the compiled Index.cshtml is available at "/Index". That will give your "AmbiguousMatchException: The request matched multiple endpoints. Matches: /Index /Index".
Just look at the Summary of UseBlazorFrameworkFiles:
Configures the application to serve Blazor WebAssembly framework files from the root path "/".
Solution is just to keep the index.html in the WASM project as is. Just look at the default Blazor WASM ASP.Net app: it hosts Blazor WASM, Razor Pages and MVC at the same time and routing is just fine.
A different solution would be to use the overload of UseBlazorFrameworkFiles, where you can give a path prefix. E.g.
app.UseBlazorFrameworkFiles("/wasm");
You will need to fix other routing.
edit:
So let's give a case. you have:
A Blazor WASM project that serves pages /, /counter, etc.
A Razor pages project that serves pages /weatherforecast, etc.
Now:
you start the app on /. This loads the WASM from the server.
Next you click on the counter icon. this doesn't change the page!: it shows the counter page and updates the navigation url, but doensn't load a new page.
Now to go to weatherforecast. This is not found in the WASM, so a new page is actually loaded from the server. (either a razor page or controller/view)
If you would go back to counter, this is not found on the server, so the server 'falls-back' to the root (/Index) and loads the WASM again. Next is look if counter is found in the WASM.
Having a dynamic /Index will disrupt this system, so you'll have to manually solve all the routing.
Right now I have it at the bottom of the _Layout.cshtml layout page that is used by every other page. The problem I'm having is that pages under the Identity area throw errors in the console when navigating to Identity pages:
POST https://localhost:5001/Identity/Account/_blazor/negotiate 404
and
blazor.server.js:1 Uncaught (in promise) Error: Cannot send data if the connection is not in the 'Connected' State.
These errors make me think I'm doing something wrong with how I enable Blazor Server in my RazorPages app.
So I'm wondering, should I only have the blazor.server.js scripts on pages that are actually using Blazor? Is there a way to make it available to Areas that putting it in the Layout seems to not do?
I believe this post answers my question:
How do I use blazor server-side inside a razor component library using areas?
By default, the SignalR service uses a relative path and was unable to find the _blazor/negotiate endpoint within an Area. The suggested code change in _Layout will make it use absolute paths and normalize to /_blazor/negotiate wherever you are in the page structure.
I know this is late but incase it help others.
I got this error when I was trying to add blazor to my existing app.
I added:
<base href="~/" />
at the end of the head tag of the _layout.cshtml file found in the shared folder.
enter image description here
I created a new ASP.NET Core 2.1 Angular project.
What is interesting is that there is index.html file inside ClientApp/src which is hosted as default page. I would like to know, which code triggers that index.html is served by default?
In my old application from universal template Controllers and Views are used which seems more naturally then serving index.html from client code.
When application is runned, some code magically inserts Angular scripts (inline.bundle.js, polyfills.bundle.js, vendor.bundle.js, main.bundle.js and styles.bundle.css) at the end of index.html file? Can someone share some light which code does that?
I want to understand this, because I want to serve content from RazorPage instead of static index.html, but in order to try anything I need to know a little more about magic behind this template.
I am new to Yii. I have a jquery file manager working with plain PHP script. Now i want to integrate it with Yii Application. The flow is like, from index it will initiate jquery function, which will search for PHP connector script. My problem is, how can i include connector script in Yii so that the Jquery can access it
If you've got the rest of the extension working, then you can create a controller within this extension's directory to handle any actions for it. Then you can use the URL rules in the configuration to send specific URLs to it.
as of now i did not create any extensions, I put the connector script under assets directory and it just worked fine. I am sure this cannot be the best practice. I would like to get help on creating custom extensions for Yii