I'm writing an ASP.Net Core app based on Freeman's book.
And while adding Blazor pages, I got a problem. When you try to go to pages that Blazor is connected to, nothing is displayed on them.
The browser console shows these errors:
Error: System.NullReferenceException: Object reference not set to an
instance of an object. at
Microsoft.AspNetCore.Components.Routing.Router.Refresh(Boolean
isNavigationIntercepted) at
Microsoft.AspNetCore.Components.Routing.Router.SetParametersAsync(ParameterView
parameters)
My Routed.razor file:
<Router AppAssembly="#typeof(Program).Assembly"
AdditionalAssemblies="new[]{typeof(Program).Assembly}">
<Found>
<RouteView RouteData="#context" DefaultLayout="typeof(AdminLayout)" />
</Found>
<NotFound>
<h4 class="bg-danger text-white text-center p-2">
No Matching Route Found
</h4>
</NotFound>
What could be the problem?
I also add a link to the repository of my project:
https://github.com/itehnoviking/CoinStore
I had to "Hack" your Program to get your solution running. Here's my version:
using CoinStore.Models;
using Microsoft.EntityFrameworkCore;
namespace CoinStore
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<StoreDbContext>(opt => opt.UseSqlServer(connectionString));
builder.Services.AddScoped<IStoreRepository, EFStoreRepository>();
builder.Services.AddScoped<IOrderRepository, EFOrderRepository>();
builder.Services.AddRazorPages();
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();
builder.Services.AddScoped<Cart>(sp => SessionCart.GetCart(sp));
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//builder.Services.AddServerSideBlazor();
//builder.Services.AddServerSideBlazor().AddCircuitOptions(o => {
// o.DetailedErrors = _env.IsDevelopment;
//}).AddHubOptions(opt => {
// opt.MaximumReceiveMessageSize = 10 * 1024 * 1024; // 10MB
//});
builder.Services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; });
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseDeveloperExceptionPage();
//app.UseStatusCodePages();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseRouting();
app.UseAuthorization();
//app.UseEndpoints(endpoints => {
// endpoints.MapControllerRoute("catpage",
// "{category}/Page{productPage:int}",
// new { Controller = "Home", action = "Index" });
// endpoints.MapControllerRoute("page", "Page{productPage:int}",
// new { Controller = "Home", action = "Index", productPage = 1 });
// endpoints.MapControllerRoute("category", "{category}",
// new { Controller = "Home", action = "Index", productPage = 1 });
// endpoints.MapControllerRoute("pagination",
// "Products/Page{productPage}",
// new { Controller = "Home", action = "Index", productPage = 1 });
// endpoints.MapDefaultControllerRoute();
// endpoints.MapRazorPages();
// endpoints.MapBlazorHub();
// endpoints.MapFallbackToPage("/admin/{*catchall}", "/Admin/Index");
//});
//app.MapControllerRoute("catpage", "{category}/Page{productPage:int}", new { controller = "Home", action = "index" });
//app.MapControllerRoute("page", "Page{productPage:int}", new { controller = "Home", action = "index", productPage = 1 });
//app.MapControllerRoute("category", "{category}", new { controller = "Home", action = "index", productPage = 1 });
//app.MapControllerRoute("pagination", "Products/Page{productPage}", new { controller = "Home", action = "index", productPage = 1 });
//app.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
//app.MapDefaultControllerRoute();
app.MapRazorPages();
app.MapBlazorHub();
app.MapFallbackToPage("/admin/{*catchall}", "/Admin/Index");
//SeedData.EnsurePopulated(app);
app.Run();
}
}
}
I then update Routed.razor - no duplication of assemblies any more which was the main issue.
<Router AppAssembly="#typeof(Program).Assembly">
<Found>
<RouteView RouteData="#context" DefaultLayout="typeof(AdminLayout)" />
</Found>
<NotFound>
<h4 class="bg-danger text-white text-center p-2">
No Matching Route Found
</h4>
</NotFound>
</Router>
And a quick fix to Index to get the references correct:
#page "/admin"
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>CoinStore Admin</title>
<link href="/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<base href="~/" />
</head>
<body>
<component type="typeof(Routed)" render-mode="Server" />
<script src="/_framework/blazor.server.js"></script>
</body>
</html>
And I get:
Related
I'm currently building a Razor web application in .NET6 who have 3 cultures.
The problem is all my anchor tags are empty in the DOM, when I click on the Contact link, it doesn't do anything.
<a class="" asp-area="" asp-page="/Contact">Contact</a>
Here is my Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddFolderRouteModelConvention("/", model =>
{
foreach (var selector in model.Selectors)
{
selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{culture?}", selector.AttributeRouteModel.Template);
}
});
});
builder.Services.AddMvc().AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix).AddDataAnnotationsLocalization();
builder.Services.Configure<RequestLocalizationOptions>(opt =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en"),
new CultureInfo("fr"),
new CultureInfo("nl")
};
opt.DefaultRequestCulture = new RequestCulture("en");
opt.SupportedCultures = supportedCultures;
opt.SupportedUICultures = supportedCultures;
opt.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider()
{
RouteDataStringKey = "culture",
UIRouteDataStringKey = "culture",
Options = opt
});
});
builder.Services.AddHttpContextAccessor();
builder.Services.AddLocalization(opt => { opt.ResourcesPath = "Resources"; });
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
var options = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
//app.UseRequestLocalization(((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
app.MapRazorPages();
app.Run();
When I manually browse to www.website.com/fr/contact-us then it works, but then when I click on the below anchor (Home), my url change to www.website.com/fr/contact-us/Index
<a asp-area="" asp-page="/">Home</a>
What am I missing?
Add the culture param to the route for all links:
<a asp-area=""
asp-page="/"
asp-route-culture="#CultureInfo.CurrentCulture.Name">Home</a>
Another way:
#{
var cltr = System.Globalization.CultureInfo.CurrentCulture.Name;
}
Home
I am trying to localize an ASP.Net Core 6 Web Application using RouteDataRequestCultureProvider.
I have configured Program.cs file as follows
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddLocalization(options => { options.ResourcesPath = "Resources"; });
builder.Services.AddMvc().AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; }).AddDataAnnotationsLocalization();
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("el-GR"),
new CultureInfo("en-US"),
};
var requestLocalizationOptions = new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en-US"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
};
requestLocalizationOptions.RequestCultureProviders.Clear();
RequestCultureProvider requestProvider = new RouteDataRequestCultureProvider();
requestLocalizationOptions.RequestCultureProviders.Insert(0, requestProvider);
var app = builder.Build();
app.UseRequestLocalization(requestLocalizationOptions);
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{culture}/{controller=Home}/{action=Index}/{id?}");
app.Run();
I have included the following Resource files
Resources/Views/Home/Index.el-GR.resx
Resources/Views/Home/Index.en-US.resx
I have included in Index.cshtml
#inject IViewLocalizer Localizer
and use it #Localizer["PropertyInResxFile"] in Index View file
I make the following requests
el-GR/Home/Index
en-US/Home/Index
I always get the default Culture localization (from Index.en-US.resx)
Thanks
I have a problem with my project. When I return a Redirect Page after login succeed. My expect link is: /Admin/Subject/Index.cshtml. But while debugging, the url is: /Subject/Index.cshtml?Area="Admin" and I get a 404 error.
return RedirectToRoute(new
{
Areas = "Admin",
controller = "Subject",
action = "Index"
});
// And
return RedirectToAction("Subject", "Courses", new { areas="Admin"});
Here is my RouteConfig
app.UseMvc(routes =>
{
routes.MapRoute(name: "MyArea",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(name: "default",
template: "{controller=Main}/{action=Login}/{id?}");
});
What am I doing wrong?
I am writing my blog site with using angular.js and asp.net webapi. I did url routing with angular.js. when I click url but I get 404 not found error. How to fix this problem?
var blogSite = angular.module("blogSite", ["ngRoute"]);
blogSite.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when("post/:post", {
teplateUrl: 'blogpost.html',
controller: 'blogPostController'
})
.otherwise({
redirectTo: 'index.html'
});
}]);
blogSite.controller("mainPageController", function ($scope, $http, $routeParams) {
var url = baseUrl + "getpost";
$http.get(url)
.success(function (data, status, headers, config) {
if (data.length > 0) {
$scope.LastBlogPosts = data;
}
else {
$scope.LastBlogPosts = null;
}
})
.error(function (data, status, headers, config) {
console.log(status);
});
});
blogSite.controller("blogPostController", function ($scope, $http, $routeParams) {
$scope.TestMessage = "Test Message"
});
index.html page
div ng-controller="mainPageController">
<ul>
<li ng-repeat="blogPost in LastBlogPosts">
{{blogPost.PostTitle}}
</li>
</ul>
</div>
</div>
</div>
<div ng-view>
</div>
You anchor should be having # to restrict redirection, putting # at the start of URL will keep you in same page & will keep you in SPA
<a href="#post/{{blogPost.PostUrl}}" class="lastPostUrl mainPagePostTitle">
{{blogPost.PostTitle}}
</a>
I am trying to pass parameter from view to controller,
This is my View:
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#foreach (var pricedetails in ViewBag.PriceTotal)
{
<div style="text-align:center; clear:both ">
<h5 class="product-title">#pricedetails.Title</h5>
</div>
<div class="product-desciption" style="height:40px">#pricedetails.Descriptions</div>
<p class="product-desciption product-old-price"> #pricedetails.PricePoints</p>
<div class="product-meta">
<ul class="product-price-list">
<li>
<span class="product-price">#pricedetails.PricePoints</span>
</li>
<li>
<span class="product-save">Get This Free</span>
</li>
</ul>
<ul class="product-actions-list">
<input type="submit" name='giftid' value="Get Gift"
onclick="location.href='#Url.Action("Index", new { id = pricedetails.PriceId })'" />
</ul>
</div>
}
}
my action method:
On submit it reaches the Action Method, but I am not able to get the PriceId for each Price
[HttpPost]
public ActionResult Index(int id=0) // here PriceId is not passed on submit
{
List<Price_T> priceimg = (from x in dbpoints.Price_T
select x).Take(3).ToList(); ;
ViewBag.PriceTotal = priceimg;
var allpoint = singletotal.AsEnumerable().Sum(a => a.Points);
var price = from x in dbpoints.Price_T
where x.PriceId == id
select x.PricePoints;
int pricepoint = price.FirstOrDefault();
if (allpoint < pricepoint)
{
return Content("<script language='javascript' type='text/javascript'>alert('You are not elgible');</script>");
}
else
{
return Content("<script language='javascript' type='text/javascript'>alert('You are elgible');</script>");
}
return View("Index");
}
Url Routing:
routes.MapRoute(
name: "homeas",
url: "Index/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
May I know what wrong I am doing ?
Please use the following in your cshtml page
#foreach (var item in Model)
{
#Html.ActionLink(item.PriceDetails, "GetGift", new { priceID = item.priceID }, new { #class = "lnkGetGift" })
}
<script type="text/javascript" src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("a.lnkGetGift").on("click", function (event) {
event.preventDefault();
$.get($(this).attr("href"), function (isEligible) {
if (isEligible) {
alert('eligible messsage');
}
else
{
alert('not eligible messsage');
}
})
});
});
</script>
and in controller
[HttpGet]
public JsonResult GetGift(int priceID)
{
List<Price_T> priceimg = (from x in dbpoints.Price_T
select x).Take(3).ToList(); ;
ViewBag.PriceTotal = priceimg;
var allpoint = singletotal.AsEnumerable().Sum(a => a.Points);
var price = from x in dbpoints.Price_T
where x.PriceId == id
select x.PricePoints;
int pricepoint = price.FirstOrDefault();
if (allpoint < pricepoint)
{
return Json(false, JsonRequestBehavior.AllowGet);
}
else
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
Please change your parameters according to the method param and price entity
Hope this helps.
I suggest you get rid of the Html.BeginForm(). Just leave the for...loop and define your "Get Gift" button like this:
<input type="button" id='giftid' name='giftid' value="Get Gift" onclick="getGift(#(pricedetails.PriceId))'" />
Then, at the bottom of the view file where the Get Gift button is located, define some JavaScript:
<script type="text/javascript">
function getGift(priceId) {
$.ajax({
type: 'GET',
url: '#Url.Action("Index", "Home")',
data: { priceId: priceId },
contentType : "json",
success:function(data){
// Do whatever in the success.
},
error:function(){
// Do whatever in the error.
}
});
</script>
By using an ajax call to get the gift data, you don't have to submit anything. This makes things a lot easier in your case. Pressing the Get Gift button simply makes an ajax call.
I don't have time to try this out myself, but hopefully the above example should get you up and running.
EDIT:
I've managed to sneak in some time to come up with an example.
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
var items = new List<int>();
items.Add(1);
items.Add(2);
items.Add(3);
return View(items);
}
public ActionResult GetGift(int priceId)
{
return RedirectToAction("Index"); // You'll be returning something else.
}
}
View
#model List<int>
#foreach (var price in Model)
{
<input type="button" id='giftid' name='giftid' value="Get Gift" onclick="getGift(#(price))" />
}
<script type="text/javascript">
function getGift(priceId) {
$.ajax({
type: 'GET',
url: '#Url.Action("GetGift", "Home")',
data: { priceId: priceId },
contentType: "json",
success: function(data) {
// Do whatever in the success.
},
error: function() {
// Do whatever in the error.
}
});
}
</script>
Hope this helps you.
I think you should correct here
<input type="button" name='giftid' value="Get Gift"
onclick="location.href='#Url.Action("Index", new { id = pricedetails.PriceId })'" />