Add Razor Page Component in MVC - c#

I've added Razor Page Component to my existing MVC application
Pages/Test.razor
#page "/test"
<h1>Hello World!</h1>
#code {
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddServerSideBlazor();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
endpoints.MapBlazorHub();
});
app.Run();
Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - MVCApp</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/MVCApp.styles.css" asp-append-version="true" />
<base href="/"/>
<script src="_framework/blazor.server.js"></script>
...
but it doesn't work: I get 404 on /test
What am I missing to make Razor Component's routing work with MVC routing?

You need to install the Microsoft.AspNetCore.Components package and add the _Host.cshtml, App.razor, _Imports.razor files to your MVC project.
_Imports.razor:
#using System.Net.Http
#using Microsoft.AspNetCore.Authorization
#using Microsoft.AspNetCore.Components.Authorization
#using Microsoft.AspNetCore.Components.Forms
#using Microsoft.AspNetCore.Components.Routing
#using Microsoft.AspNetCore.Components.Web
#using Microsoft.AspNetCore.Components.Web.Virtualization
#using Microsoft.JSInterop
#using Project
_Host.cshtml:
#page "/"
#namespace Project.Pages
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#{
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />
App.razor:
#using Microsoft.AspNetCore.Components.Routing
<Router AppAssembly="#typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="#routeData" />
<FocusOnNavigate RouteData="#routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView>
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Your Endpoints:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
Test Result:
If you want to use the UI in Blazor, you can also copy MainLayout.razor from a Blazor App and use it in App.razor like this:
//...
<RouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)" />
//...
<LayoutView Layout="#typeof(MainLayout)">
//...
Note that if you do this, your default page will be a Razor Component with #page "/" defined instead of Index.cshtml.

Related

Blazor Allow Anonymous For Razor Page

I have a .net cor 3.1 Blazor server project. I use the default identity system in this project. I want to access a specific razor page without login. How do I do that? Any Idea?
I tried adding #attribute [AllowAnonymous] to the razor page. But it did not work for me
_Host.cshtml
page "/"
#using Microsoft.AspNetCore.Authorization
#namespace has.Pages
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#attribute [Authorize]
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>has</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="css/custom_styles.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="_content/AntDesign/css/ant-design-blazor.css" rel="stylesheet" />
<link href="_content/Blazor.ContextMenu/blazorContextMenu.min.css" rel="stylesheet" />
<script src="_content/BlazorInputFile/inputfile.js"></script>
<script src="~/js/site.js"></script>
</head>
<body>
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" />
</app>
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
Reload
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.server.js"></script>
<script src="_content/AntDesign/js/ant-design-blazor.js"></script>
<script src="_content/Blazor.ContextMenu/blazorContextMenu.min.js"></script>
<script src="https://kit.fontawesome.com/863157cf0e.js" crossorigin="anonymous"></script>
</body>
</html>
App.razor
<CascadingAuthenticationState>
<Router AppAssembly="#typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="#typeof(MainLayout)">
<Error404 />
</LayoutView>
</NotFound>
</Router>
<AntContainer />
</CascadingAuthenticationState>
I found an answer. I created another _Host.cshtml with #attribute [AllowAnonymous] in a separate folder inside of the Pages folder and I put my razor page in that folder.
Add #layout PublicLayout to your anonymous access component. In my case, MyAnonymousComponent.razor. PublicLayout is PublicSection/PublicLayout.razor
My project structure is like this
MyProject
-Pages
-Section1
-Section2
-Shared
_Layout.cshtml
-PublicSection // This folder has anonymous access components
_Host.cshtml
_Layout.cshtml
MyAnonymousComponent.razor
PublicApp.razor
PublicLayout.razor
_Host.cshtml
-Shared
MainLayout.razor
App.razor
_Imports.razor
Program.cs
Startup.cs
PublicSection/_Host.cshtml
#page "/publicsection"
#using has.Pages.PublicRazor
#using Microsoft.AspNetCore.Authorization
#namespace has.Pages
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#attribute [AllowAnonymous]
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<base href="~/PublicSection" />
// rest is same as Original _Host.cshtml file
</head>
<body>
<app>
<component type="typeof(PublicApp)" render-mode="ServerPrerendered" />
</app>
// rest is same as Original _Host.cshtml file
</body>
</html>
PublicApp.razor
<CascadingAuthenticationState>
<Router AppAssembly="#typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="#routeData" DefaultLayout="#typeof(PublicLayout)" />
</Found>
<NotFound>
<LayoutView Layout="#typeof(PublicLayout)">
<Error404 />
</LayoutView>
</NotFound>
</Router>
<AntContainer />
</CascadingAuthenticationState>
PublicLayout.razor
#inherits LayoutComponentBase;
<Content Class="site-layout-background content-pan">
#Body
</Content>
#code {
}
Startup.cs
...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("~/PublicSection/{**segment}","/PublicRazor/_Host");
endpoints.MapFallbackToPage("/_Host");
});
...

Blazor-Server sidenav/sidebar for Identity/Account/Manage that looks like NavMenu.razor

Default Blazor project is very inconsistent when it comes to UI. For blazor components, there is a sidenav. But for account manage /Identity/Account/Manage there is no sidenav as that is .cshtml not .razor page.
I know that to have consistent UI I have to have probably two side nav and maintain exactly the same layout for both of them. Still, maybe there is already some example of sidenav for /Identity/Account/Manage that looks exactly as that available for blazor components?
The most welcome solution is use existing blazor navbar (Shared/NavMenu.razor) in account management (/Identity/Account/Manage) pages
I have created a PR against your sample on GitHub. The change is to the _Layout.cshtml used by Identity - it's not perfect, but shows the technique.
_Layout.cshtml
#using Microsoft.AspNetCore.Hosting
#using Microsoft.AspNetCore.Mvc.ViewEngines
#inject IWebHostEnvironment Environment
#inject ICompositeViewEngine Engine
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - BlazorAuthTemplate</title>
<base href="~/" />
<link rel="stylesheet" href="~/Identity/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/Identity/css/site.css" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>
<div class="sidebar">
<component type="typeof(BlazorAuthTemplate.Shared.NavMenu)" render-mode="ServerPrerendered" />
</div>
<div class="main">
<div class="top-row px-4 auth">
<div class="d-sm-inline-flex flex-sm-row-reverse">
#{
var result = Engine.FindView(ViewContext, "_LoginPartial", isMainPage: false);
}
#if (result.Success)
{
await Html.RenderPartialAsync("_LoginPartial");
}
else
{
throw new InvalidOperationException("The default Identity UI layout requires a partial view '_LoginPartial' " +
"usually located at '/Pages/_LoginPartial' or at '/Views/Shared/_LoginPartial' to work. Based on your configuration " +
$"we have looked at it in the following locations: {System.Environment.NewLine}{string.Join(System.Environment.NewLine, result.SearchedLocations)}.");
}
</div>
About
</div>
<main role="main" class="content px-4 pb-3">
#RenderBody()
</main>
</div>
</app>
<script src="~/Identity/lib/jquery/dist/jquery.min.js"></script>
<script src="~/Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/Identity/js/site.js" asp-append-version="true"></script>
#RenderSection("Scripts", required: false)
<script src="/_framework/blazor.server.js"></script>
</body>
</html>

How to load jQuery inside a Blazor web app?

The example provider here does not work
How to use jQuery UI from Blazor component
https://blazorfiddle.com/s/kg13ms5x
This is how you initialize the resizable widget from Blazor. You can place this code where you want, preferably in the App or layout components...
#inject IJSRuntime JSRuntime
#code {
protected async override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeAsync<object>("jQueryWidgets.initialize");
}
}
Add the following script... jQueryWidgets is the namespace, initialize is the 'name' of the function...
JavaScript (_Host.cshtml, if you use Blazor Server )
<script src="_framework/blazor.server.js"></script>
<script>
window.jQueryWidgets = {
initialize: function () {
$("#resizable").resizable();
}
};
</script>
Note that you should also add the necessary jQuery files. Place them within the head html element in _Host.cshtml, if you use Blazor Server
#Isaac's code is correct.It seems that you do not have proper references to jquery-ui:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ServerSideBlazor</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
#*Add below references*#
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<style>
#resizable {
width: 100px;
height: 100px;
background: #ccc;
}
</style>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
I suggest that you could create a new blazor project with visual studio 2019 and asp.net core 3.0 sdk.

Can not attach chosen plugin to asp.net mvc 4 site

I have been trying to attach this http://harvesthq.github.io/chosen/ to my asp.net mvc 4 site, but still to no avail.
I tried doing the same with simple WebForms, and it was a success.
Nuget packages were downloaded to default locations in both cases.
in all I downloaded these packages:
Jquery-2.1.1
Jquery-ui-1.10.4
chosen-1.1.0
chosen.jquery-1.1.0
Scripts are located in /Scripts folder and Css file in /Content
I have been using Visual Studio 2013.
Here is the code of View (simplified):
#model IEnumerable<modelnamehere>
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "TestedController", FormMethod.Get))
{
some code here;
}
<select multiple class="mySelector" data-placeholder="Choose...">
<option>Select 1</option>
<option>Select 2</option>
<option>Select 3</option>
</select>
<link href="#Url.Content("~/Content/chosen.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/chosen.jquery.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$(".mySelector").chosen();
})
</script>
And here is _Layout.cshtml shared page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - ASP.NET MVC</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">#Html.ActionLink("ASP.NET MVC", "Index", "Home")</p>
</div>
<div class="float-right">
<section id="login">
</section>
<nav>
<ul id="menu">
<li>#Html.ActionLink("Testing Page", "Index","TestedController")/li>
</ul>
</nav>
</div>
</div>
</header>
<div id="body">
#RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
#RenderBody()
</section>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© #DateTime.Now.Year - ASP.Net MVC</p>
</div>
</div>
</footer>
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
</body>
</html>
I`m kinda new to using JQuery, so if there is some explanation to the wrongs steps I have done, it would be much app

Ajax.BeginForm results in redirect to partial view instead of in-place

My Search.cshtml has a div named "search-results" that is to be updated. SearchResults is the action name. I have done this many times on MVC2/VS2008 projects, but this is my first using MVC3 and VS2010.
The problem is, instead of my search result being rendered in my div, it clicking submit is redirecting me displaying my partial as a standalone page.
I have read that this may be because Ajax is not enabled. My _Layout.cshtml looks like this:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<script src="#Url.Content("~/Scripts/2011.2.712/jquery-1.5.1.min.js")" type="text/javascript"></script>
<link href="#Url.Content("~/Content/themes/base/jquery.ui.core.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/themes/base/jquery.ui.datepicker.css")" rel="stylesheet"  type="text/css" />
<link href="#Url.Content("~/Content/themes/base/jquery.ui.theme.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/main.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/2011.2.712/jquery-1.5.1.min.js")" type="text/javascript"></script>
#(Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add("telerik.common.css").Add("telerik.transparent.css").Combined(true).Compress(true)))
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
#(Html.Telerik().Menu()
.Name("menu")
.Items(menu => {
menu.Add().Text("Home").Action("Index", "Home");
menu.Add().Text("About").Action("About", "Home");
menu.Add().Text("Employees").Action("List", "Employee");
}))
</div>
<div id="main">
#RenderBody()
<div id="footer">
</div>
</div>
</div>
#(Html.Telerik().ScriptRegistrar().DefaultGroup(group => group.Combined(true).Compress(true)))</body>
</html>
Do I need to add MicrosoftMvcAjax.js or jquery.unobtrusive-ajax.js in? My web.config (root) contians the following:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
If I add MicrosoftMvcAjax.js in at the end of the element, I get an error sayning namespace 'Type' is undefined error from the first line of MicrosoftMvcAjax.js:
Type.registerNamespace('Sys.Mvc');Sys.Mvc.$create_AjaxOptions=function(){return {};}
What am I missing here. I am sure my code is fine, as it copied alsmost verbatim from my MVC2 projects.
You forgot to include the jquery.unobtrusive-ajax.js script to your page (adjust the path as necessary):
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
As far as Microsoft*.js scripts are concerned, they are obsolete in ASP.NET MVC 3 and should no longer be used unless you are porting some legacy application. They have been replaced by jQuery.
Ok, figured out my problem.
I was calling Ajax.BeginForm with the AjaxOption OnSuccess pointint to a js function that updated my place holder. But this is not needed, with unobtrusive. Once I removed the OnSucces from the Ajax options everything started working.
~S

Categories

Resources