I've built a small Blazor website for myself, using a free template which has a bunch of javascript files with it.
Everything seems to be working fine except for one thing.
When a user reloads (F5) a project detail page, all the html markup dissapears and the console shows a bunch of error logs, indicating that it cannot find the related javascript files. Reloading any other page works fine.
Here is the razor page
#page "/project/{Slug}"
#using DOGA.Data
#using DOGA.Services
#inject ProjectService projectService
#inject NavigationManager navigationManager
#if (_project == null)
{
<p><em>Loading...</em></p>
}
else
{
<section id="pricing" class="pricing-area">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10">
<div class="section-title text-center pb-20">
<h3 class="title">#_project.Name</h3>
<p class="text">
#((MarkupString)_project.Description)
#if (_project.BulletPointList.Items.Any())
{
<br />
#_project.BulletPointList.Name
<br />
<br />
<ul style="text-align:left;">
#foreach (var item in _project.BulletPointList.Items)
{
<li>
<i class="lni-check-mark-circle"></i> #item
</li>
}
</ul>
}
</p>
</div> <!-- section title -->
</div>
</div> <!-- row -->
#foreach (var image in _project.DetailImages)
{
<div class="row justify-content-center">
<div class="col-lg-12 col-md-7 col-sm-9">
<div class="pricing-style-one mt-40 wow fadeIn" data-wow-duration="1.5s" data-wow-delay="0.2s">
<div class="pricing-header text-center">
<h5 class="sub-title">#image.ImageName</h5>
</div>
<div class="text-center">
<img src="#image.ImageLink" alt="#image.ImageName">
</div>
<div class="text-center top-buffer">
<br />
#image.ImageDescription
</div>
#if (image.BulletPoints.Any())
{
<br />
<div class="pricing-list">
<ul>
#foreach (var item in image.BulletPoints)
{
<li><i class="lni-check-mark-circle"></i> #item</li>
}
</ul>
</div>
}
</div>
</div>
</div>
}
</div>
</section>
}
#code {
[Parameter]
public string Slug { get; set; }
private Project _project { get; set; }
protected override async Task OnInitializedAsync()
{
_project = await projectService.GetProjectAsync(Slug);
if (_project == null)
{
navigationManager.NavigateTo("/");
}
}
}
The error appears both locally and on a published azure site.
The site is deployed on azure for now. Mind you it is in Dutch.
The error appears when going to portfolio page, clicking on one of the three projects and then hard refreshing.
https://dogasolutions.azurewebsites.net/
EDIT: after fixing the references by adding a '/' (thanks to gsharp), the page seems to reload fine except for the blazor javascript file.
In the _host.cshtml inside the body tags:
<app>
#(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="/_framework/blazor.server.js"></script>
I found out what the culprit was. I used an online template to replace most of my _Host.cshtml file. By doing so I had overwritten the base tag in my head tag.
Simply adding the following code inside my head tag fixed the issue completely.
<base href="~/" />
Without this, blazor cannot correctly resolve the connection when going into detail pages (e.g. domain/page/{parameter})
Related
I'm using ASP NET CORE MVC 5.
I have a View ("ChooseServices") which, depending on the parameter passed, displays 1 or N PartialViews (Forms):
ChooseServices.cshtml:
<div class="col">
#if (Model.OfferServiceA)
{
<partial name="_FormA" />
}
#if (Model.OfferServiceB)
{
<partial name="_FormB" />
}
#if (Model.OfferServiceC)
{
<partial name="_FormC" />
}
</div>
After answering each Form individually, I want to display a default message which is another PartialView ("_confirmation.cshtml") in place of the Form.
Something like this:
(after submit Form-A)
(and after submit Form-C)
In summary, after submitting a Form (partial view), I want it be replaced by another PartialViews, all inside the View "ChooseServices".
[EDIT - Some code]
CONTROLLER:
public class SomeServiceController : Controller
{
// A survey brings to here.
public IActionResult ChooseServices(SuggestedServicesDTO dto)
{
return View(dto);
}
}
VIEWS (ignoring css)
ChooseServices.cshtml
#model SuggestedServicesDTO
<section >
<div class="container">
<div class="row">
<div class="col">
#if (Model.OfferServiceA)
{
<partial name="_FormA" />
}
#if (Model.OfferServiceB)
{
<partial name="_FormB" />
}
#if (Model.OfferServiceC)
{
<partial name="_FormC" />
}
</div>
</div>
</div>
</section>
_Form{x}.cshtml
{x} is the service name.
<div class="card">
<div class="card-body">
<h3>THIS IS THE FORM-{x}.</h3>
<form asp-action="??IDK what put here">
<div>
<label>Select an option:</label>
<!-- Radio buttons Begin -->
<div>
<label for="service{x}Opt{N}">
<input type="radio" name="optionsService{x}" id="service{x}Opt{N}" value="someValue1">
<span>Option QWERTY</span>
</label>
</div>
<div>
<label for="service{x}Opt{N}">
<input type="radio" name="optionsService{x}" id="service{x}Opt{N}" value="someValue2">
<span>Option ASDFGH</span>
</label>
</div>
<!-- others options here -->
<!-- Radio buttons end-->
</div>
<div>
<input type="submit" value="Submit {x}"/>
</div>
</form>
</div>
</div>
_Confirmation.cshtml
(Just a message, nothing important)
<div class="card">
<div class="card-body">
<div>
<h3>Thanks for answering!</h3>
<p>bla bla bla bla</p>
<button type="button" onclick="window.open('someurl', '_blank').focus();">
Do something...
</button>
</div>
</div>
</div>
I don't know what to do after submit de Forms{x}.
Dear friends I am currently creating an admin panel for user where they can easily can publish their articles. I also want to add to my form a little fileuploader but sadly I got some problems with DROPZONEJS.JS file in POST method. The main problem is I cannot give URL to project's local file in order to download to file there where website will access those file in order to publish them with current article's id. Please let me know if there is something not understandable.
#{
ViewBag.Title = "Uppy";
}
#{
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<div class="content d-flex flex-column flex-column-fluid" id="kt_content">
<!--begin::Entry-->
<div class="d-flex flex-column-fluid">
<!--begin::Container-->
<div class="container">
<!--begin::Card-->
<div class="card card-custom gutter-b">
<div class="card-header">
<div class="card-title">
<h3 class="card-label">File Upload</h3>
</div>
</div>
<!--begin::Form-->
<form>
<div class="card-body">
<div class="form-group row">
<label class="col-form-label col-lg-3 col-sm-12 text-lg-right">Multiple File Upload</label>
<div class="col-lg-4 col-md-9 col-sm-12">
<div class="dropzone dropzone-default dropzone-primary" id="kt_dropzone_2">
<div class="dropzone-msg dz-message needsclick">
<h3 class="dropzone-msg-title">Drop files here or click to upload.</h3>
<span class="dropzone-msg-desc">Upload up to 10 files</span>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-form-label col-lg-3 col-sm-12 text-lg-right">File Type Validation</label>
<div class="col-lg-4 col-md-9 col-sm-12">
<div class="dropzone dropzone-default dropzone-success" id="kt_dropzone_3">
<div class="dropzone-msg dz-message needsclick">
<h3 class="dropzone-msg-title">Drop files here or click to upload.</h3>
<span class="dropzone-msg-desc">Only image, pdf and psd files are allowed for upload</span>
</div>
</div>
</div>
</div>
</div>
#using (Html.BeginForm("Uppy",
"FileUpload",
FormMethod.Post,
new { enctype = "multipart/form-data" })) //multipart/form-data gives functionlity to inputes (search at web);
{
<div class="card-footer">
<div class="row">
<div class="col-lg-3"></div>
<div class="col-lg-4">
<input type="submit" value="Submit" class="btn btn-light-primary mr-2" />
<button type="reset" class="btn btn-primary">Cancel</button>
</div>
</div>
</div>
}
</form>
<!--end::Form-->
</div>
<!--end::Card-->
<!--end::Row-->
</div>
<!--end::Container-->
</div>
<!--end::Entry-->
</div>
<!--end::Content-->
By the way my own upload code is working correctly and also sends choosen file to url location where I wrote in controller.
<label for="file">Upload File:</label>
<input type="file" name="file" id="file" class="btn-hover-bg-success" />
<br>
<br>
<input type="submit" value="Upload Image" />
<br>
<br>
#ViewBag.Message
This is my FileUploadController:
[HttpPost]
public ActionResult Uppy(HttpPostedFileBase file)
{
ADAPTIVE_TESTEntities ent = new ADAPTIVE_TESTEntities();
Adaptive.News.Models.NEWS news = new Adaptive.News.Models.NEWS();
if (file != null && file.ContentLength > 0)
try
{
var path = Path.Combine(Server.MapPath("~/Content/images"),
Path.GetFileName(file.FileName));
file.SaveAs(path);
news.PICTUREPATH = path;
ent.NEWS.Add(news);
ent.SaveChanges();
ViewBag.Message = "File uploaded successfully";
}
catch (Exception ex)
{
ViewBag.Message = "ERROR: " + ex.Message.ToString();
}
else
{
ViewBag.Message = "You have not specified a file.";
}
return View();
}
it is not obvious to me, what and where really your problem is. What do you mean with having problem. Is your problem with Dropzone.JS or with C#? Anyway, I examined your code slightly and have some ideas what your problem could be.
FIRST OF ALL: You have 2 DIV containers, which you use as Dropzone elements assigning them the css class "dropzone". Furthermore you generate a FORM element with ASP.Net HTML-Helper.
By default you have 2 options using Dropzone.
Declarative instantiation via assigning css class "dropzone" to any HTML element.
Dropzone discovers all DOM elements with class="dropzone" automatically and instantiates them.
Programmatically instantiating: You instantiate Dropzone by passing the id of the container element and THE OPTIONS CONTAINING POST URL to the Dropzone constructor.
DECLARATIVE DROPZONE
You must pay attention to this detail: If you use FORM element as Dropzone container element, Dropzone uses "action" attribute of the FORM element as post URL. But if you use
DIV element as container, then you get most possibly a JavaScript error. Because DIV elements do usually NOT have "action" attribute. If you use DIV as Dropzone container (and in your code you use it 2 times), you will get following JavaScript error:
dropzone.js:1027 Uncaught Error: No URL provided.
at new Dropzone (dropzone.js:1027)
at dropzone.js:2907
at Function.Dropzone.discover (dropzone.js:2919)
at Dropzone._autoDiscoverFunction (dropzone.js:3491)
at HTMLDocument.init (dropzone.js:3456)
In this case you have two options solve the problem:
Use FORM element instead of DIV as Dropzone container.
Add action="/your/post/url" to your DIV element, which you use as Dropzone container.
Where I would prefer the first option. Because it is not common that DIV elements have action attribute.
I have a build for the screen on which I received payment information on the eCommerce-like page I was working on. Here, the person can trade on his / her name or someone else and I need to add a button to update the incoming information.
In order to update the information I have a method in the controller, but when I press the button, I cannot send the data to the controller. I noticed that this is not because Foreach is printed. Does anyone have this problem or know the solution?
#model List<CartVM>
#{
ViewData["Title"] = "Index";
}
<form>
#foreach (var item in Model)
{
<li>
<div>
<h4>
#item.SubcategoryName
<label asp-for="#item.Amount" class="col-md-4 pull-right text-right">Total Amount: #item.Amount TL</label>
<label asp-for="#item.Count" class="col-md-3 pull-right">Count: #item.Count</label>
</h4>
</div>
</li>
<li>
<div class="order-buttons">
<input asp-controller="Payment" asp-action="Edit" class="btn bg-primary" value="Edit All" />
</div>
</li>
}
</form>
Controller:
public void Edit(CartVM cartVM)
{
_cartService.AddToCart(cartVM);
}
I try to create a helper in my project.
This is my code:
#using VrBlog.Models;
#helper Render(Post post, System.Web.Mvc.HtmlHelper html, bool isAdmin, bool showComments)
{
<div class="postTitle">#post.Title</div>
<div class="postContainer">
<div class="postTabs">
<div class="dateTab">
<div class="month">#post.DateTime.Value.ToString("MMM").ToUpper()</div>
<div class="day">#post.DateTime.Value.ToString("dd")</div>
</div>
<div class="commentsTab">
#post.Comments.Count
</div>
</div>
<div class="postContent">
<div class ="postBody">#html.Raw(post.Body)</div>
<div class="tagList">
#foreach (Tag tag in post.Tags)
{
<span class="tag">#tag.Name</span>
}
</div>
<div class="linkList">
#{ string url = "http://www.mattblagden.com/posts/details/" + post.Id;}
</div>
</div>
</div>
if (showComments)
{
<div id="commentsContainer">
<a id ="comments"></a>
#foreach (Comment comment in post.Comments.OrderBy(x => x.DateTime))
{
<div class="comment">
<div class="commentName">
#if (!string.IsNullOrWhiteSpace(comment.Email))
{
#comment.Name
}
else
{
#comment.Name;
}
</div>
said:
<div class="commentBody">#html.Raw(html.Encode(comment.Body).Replace("\n", "<br/>"))</div>
<div class="commentTime">at #comment.DateTime.Value.ToString("HH:mm") on #comment.DateTime.Value.ToString("yyyy/MM/dd")</div>
</div>
}
<div id="commentEditor">
<div id="commentPromt">Leave a comment!</div>
<form action="#Href("~/Views/Posts/Comment/" + post.Id)" method="post">
<input type="text" id="commentNamePromt" name="name"/>Name (required)<br/>
<input type="text" id="commentEmailPromt" name="email" />Email (optional)<br/>
<textarea id="commentBodyInput" name="body" rows="10" cols="60"></textarea><br/>
<input type="submit" id="commentSubmitInput" name="submit" value="Submit!"/>
</form>
</div>
</div>
}
}
And after this, I try to call it from the view. My helper is in the AppCode folder inside the project.
I try to call it like this
#foreach (Post post in Model)
{
#PostHelper.Render(post,Html,isAdmin, false)
}
But I get the following error:
Error CS0103 The name 'PostHelper' does not exist in the current context
How I can fix this and why it not visible?
If you are calling the helper on the same page, try following:
#foreach (Post post in Model)
{
#Render(post, Html, isAdmin, false)
}
Change this
#foreach (Post post in Model)
{
#PostHelper.Render(post,Html,isAdmin, false)
}
to
#foreach (Post post in Model)
{
#Render(post,Html,isAdmin, false)
}
Rename your folder in App_Code
"We can define the #helper method outside of our view template, and enable it to be re-used across all of the view templates in our project.
We can accomplish this by saving our #helper methods within .cshtml/.vbhtml files that are placed within a \App_Code directory that you create at the root of a project."
I have a website in Asp.Net that I am trying to port to MVC 3 and I have only worked with MVC 2 before. I stumbled across the following asp function
<div class="popup-holder">
<ul class="popups">
<asp:Repeater runat="server" ID="ourTeamRepeater" OnItemDataBound="ourTeamRepeater_ItemDataBound">
<ItemTemplate>
<asp:Panel ID="pnlTeamMember" runat="server">
<li id="TeamMember" runat="server" class="memberImage">
<asp:Image runat="server" ID="memberImg" />
</li>
<div class="popup">
<div class="img-holder">
<asp:Image runat="server" ID="memberImgBig" />
</div>
<div class="popup-text-t">
<div class="close">
close
</div>
</div>
<div class="popup-text">
</div>
<div class="popup-text-b">
</div>
<div class="holder">
<asp:Literal ID="memberDescription" runat="server" />
</div>
</div>
</asp:Panel>
</ItemTemplate>
</asp:Repeater>
</ul>
it looks like maybe this works similarly to a for loop, but I'm not quite positive how to convert it to MVC 3 architecture.
Porting an existing WebForms application to ASP.NET MVC is not only about blindly translating line by line some WebForms view code that you have. You should take into account the semantics of the target platform. For example converting this asp:Repeater into an ugly foreach loop instead of taking into account things like view models, display templates would not be very good.
So in ASP.NET MVC you start by designing view models:
public class MemberViewModel
{
public int Id { get; set; }
public string Description { get; set; }
}
then you design a controller action which populates this view model:
public ActionResult Index()
{
IEnumerable<MemberViewModel> model = ...
return View(model);
}
then you write a strongly typed view in which you invoke a display template:
#model IEnumerable<MemberViewModel>
#Html.DisplayForModel()
and then you define a display template which will be rendered for each element of the collection (~/Views/Shared/DisplayTemplates/MemberViewModel.cshtml):
#model MemberViewModel
<li id="TeamMember" class="memberImage">
<img src="Url.Action("ThumbnailImage", new { id = Model.Id })" alt=""/>
</li>
<div class="popup">
<div class="img-holder">
<img src="Url.Action("FullImage", new { id = Model.Id })" alt=""/>
</div>
<div class="popup-text-t">
<div class="close">
close
</div>
</div>
<div class="popup-text"></div>
<div class="popup-text-b"></div>
<div class="holder">
#Html.DisplayFor(x => x.Description)
</div>
</div>
Now you will notice the two additional ThumbnailImage and FullImage controller actions that will allows us to fetch the images of the members given the member id. For example:
public ActionResult ThumbnailImage(int id)
{
byte[] thumbnail = ...
return File(thumbnail, "image/jpeg");
}
Now that's more like ASP.NET MVC. As you can see it's a totally different pattern than classic WebForms.
You're quite right to suppose that the MVC equivalent of an asp:Repeater is
<% foreach( var item in Model )
{ %>
<!-- Your HTML Markup -->
<% } %>
You're right about it being similar to a for loop. A simple implementation might look like this:
<div class="popup-holder">
<ul class="popups">
<%foreach(var item in Model.Items) { %>
<div id="pnlTeamMember">
<img src="<%: item.MemberImageSrc %>" ID="memberImg" />
<div class="popup">
<div class="img-holder">
<img src="<%: item.MemberImgBigSrc %>" ID="memberImgBig" />
</div>
<div class="popup-text-t">
<div class="close">
close
</div>
</div>
<div class="popup-text">
</div>
<div class="popup-text-b">
</div>
<div class="holder">
<%: item.MemberDescription %>
</div>
</div>
</div>
<% } %>
</ul>
You'll notice that there are no longer any controls with runat="server", nor are there any events linked to handlers in the code-behind. Instead, we are assuming that the controller has populated the Model object with objects representing the data that we need to display. That is the role of the controller when using MVC.
A repeater is just a loop that provides databinding so that you can access the items in the collection that you are looping. If you look in the ourTeamRepeater_ItemDataBound method you will find the code that uses the databound items to populate the elements in the item template with data.
Usually you can just use a foreach loop in MVC to loop the items. Example:
<% foreach (var item in items) { %>
<div class="holder">
<%= item.Description %>
</div>
<% } %>