I am trying to get to grips with Razor, and have hit a basic snag. I generate a small menu based on the users authenticated status. But, I am doing it wrong.
<div>
Home
List
#if (Request.IsAuthenticated)
{
Upload
Logout
}
</div>
It doesn't like the HTML within my {} section. I think it expects an HTML tag... Something like <div>, but because I am using  , it's not happy. How do I do this?
Additionally, I am trying to handle an image tag. But this is failing dismally.
#using GalleryPresentation.Models
#model IndexModel
#{
ViewBag.Title = "Craig and Melanie's Digital Moments";
}
<br/>
<div style="text-align: center">
<img src="#Html.Raw(m => m.RandomImageUrl) />
</div>
where my model is simply:
{
public class IndexModel
{
public string RandomImageUrl { get; set; }
}
}
Razor cannot detect that you are entering HTML mode. Use the special <text> Razor tag to indicate you are in HTML mode.
If you want to display content from HTML, you may use for example #Html.Raw() method. So your code migth be
<div>
Home
List
#if (Request.IsAuthenticated)
{ #Html.Raw("
Upload
Logout ")
}
</div>
nbsp means non breaking space. It is used in html to insert spaces in the middle. Since you are in the middle of a razor code, the compiler doesn't know when you use an html code, at once without a directive. Since it'll give a compile error. This is more like preprocessor directives in c. (if you know #include ). Here you simply have to use the . The correct code will look as follows.
<div>
Home
List
#if (Request.IsAuthenticated)
{
<text>
</text>
Upload
<text>
</text>
Logout
}
</div>
Related
I'm wondering if anybody has any views or knowledge on where the future of TagHelpers & Razor Components lay. My question is only with regard to initial rendering. Not using C# code on the client-side.
I love the razor component model of working in the sense that the basic component is laid out in markup, then there is code behind.
This being compared to TagHelpers generating the markup.
Take this TagHelper label component I use for example...
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace gMIS.TagHelpers
{
[HtmlTargetElement("glabel", TagStructure = TagStructure.WithoutEndTag)]
public class glabelTagHelper : TagHelper
{
#region Attributes
[HtmlAttributeName("id")]
public string id { get; set; }
[HtmlAttributeName("class")]
public string cls { get; set; }
[HtmlAttributeName("xy")]
public string xy { get; set; }
[HtmlAttributeName("style")]
public string style { get; set; }
[HtmlAttributeName("value")]
public string value { get; set; }
#endregion Attributes
public override void Process(TagHelperContext context, TagHelperOutput output)
{
//START with the container DIV
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
if (id != null) output.Attributes.Add("id", id);
if ((xy != null) && (xy != null)) output.Attributes.Add("class", "xy" + xy);
if (style != null) output.Attributes.Add("style", "display:inline-block; font-weight:bold;" + style); //*** Any subsequent WIDTH passed in with supercede the default provided here!
else output.Attributes.Add("style", "display:inline-block; font-weight:bold;");
if (cls != null) output.Attributes.Add("class", cls);
//Insert data value
if (value != null) output.Content.AppendHtml(value);
}
}
}
I would love it if this could be coded something like...
<div id="{inject id}" class="{inject class}" style="{inject style}">{inject text}</div>
...rather than using C# to create the basic markup.
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
Then the code behind interacts (only server-side) to finish the configuration of the basic component markup. That way, you can see the basic markup rather than the more difficult to read and visualize C# construction of the markup.
With a basic label this seems like not much of a gain, but with more complex components, being able to visualize the markup would be a real boon.
<div class="{inject class}" id="{inject id}" style="{inject style}">
<input name="{inject name}" id="{inject id}" style="{inject style}" type="text" value="-4" data-val-required=" Req!" data-val="true">
<input id="{inject id}" style="{inject style}" type="text" placeholder="Start typing here to search..." autocomplete="off">
<select id="{inject id}" style="{inject style}" size="1">
</select>
<script type="text/javascript">
$(document).ready(function () { $('#ext_IT_Task_Reported_By_ID').glookupInit('/TagHelpers/InternalContactLookup'); });</script>
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="{inject id}"></span>
</div>
Does anybody know where Taghelpers is heading the longer term? Towards the Razor Component way of construction perhaps. Apologies if my post isn't clear enough. I have thought hard about how to communicate my question. I do hope it's not confusing.
Not sure exactly what you're asking here, but I think you're not understanding how tag helpers work. You don't have to add each attribute manually to the output and you certainly don't need backing properties if you don't actually need the value for the purposes of the tag helper. Razor leaves any additional attributes unmolested.
[HtmlTargetElement("glabel")]
public class glabelTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
var style = "display:inline-block; font-weight:bold";
if (output.Attributes.TryGetAttribute("style", out var attr))
{
style += $";{attr.Value}";
}
output.Attributes.SetAttribute("style", style);
}
}
Based on your code, the only thing you're modifying is the style attribute, so everything else, including the content, can and will just come over as-is. Then, for the style, you just need to see if the attribute already exists, and if so, append that to your custom style. With just the code above:
<glabel id="foo" class="foo" style="width:100px">
<!-- child content here -->
</glabel>
Will result in:
<div id="foo" class="foo" style="display:inline-block;font-weight:bold;width:100px">
<!-- child content here -->
</div>
The child elements would need to be their own tag helpers if you need to do special stuff there. A tag helper only operates on the immediate tag itself, not an entire block of HTML. You can get the child content and manually modify it, but you'd be doing so as just a string, having to use stuff like regex. Suffice it to say, that would be less than ideal.
Chris Pratt (How do I reference another user properly?)
Unfortunately, you do misunderstand the question. I'm not having problems creating TagHelpers or understanding how they work. We have some 20-25 TagHelpers that we have developed, ranging from Dynamic lookups to our own fairly extensive and powerful grid. Example of grid usage below...
<ggrid id="grdTaskSearchResults"
url="Task_Search?handler=results&userguid=#Model.UserGUID&manager=#Model.Manager"
sortby="#Model.Opt_SortCol"
sortdir="#Model.Opt_SortDir"
pagesize="100"
style="height:100%; width:100%;">
<cols>
<coltemplate style="white-space:nowrap;">
<a onclick="gNewWindowAndTitle('View IT Call Log', null, null, 'Task_Summary?userguid=#Model.UserGUID&taskId={Task_ID}')" title="View IT Call Log"><img class="smallIcon" src="/Icons/Magnify.gif" /></a>
<gpdialog btnexit="Cancel" btnsubmitandclose="Save" title="Edit Call Log" url="Task_CRUD?userguid=#Model.UserGUID&manager=#Model.Manager&crud=u&taskId={Task_ID}" callback="ggridReload('grdTaskSearchResults')" linkicon="/Icons/Edit.gif" hideif="('#Model.Manager' !== 'true')" suppresstitle="true" />
<gpdialog btnexit="Cancel" btnsubmitandclose="Save" title="Add Note to Call Log" url="Task_Note_CRUD?userguid=#Model.UserGUID&taskId={Task_ID}" callback="ggridReload('grdTaskSearchResults')" linkicon="/Icons/NewAddition.gif" suppresstitle="true" />
<img class='smallIcon' src="/Icons/Exclamation.gif" alt='Not Responded yet!' hideif="{Responded}===true" />
</coltemplate>
<col heading="ID" fld="Task_ID" />
<col heading="Type" fld="Task_Type" style="white-space:nowrap;" />
<col heading="Status" fld="Task_Status" />
<coltemplate heading="Reported By">
<a target="_blank" href="https://gmis.info/entity/entity.asp?ec=1&code={Reported_By_ID}">{Reported_By_Name}</a>
</coltemplate>
<col heading="Date Entered" fld="Date_Entered" style="white-space:nowrap;" format="ddMMMyy" />
<col heading="NAB" fld="NAB_Initials" style="white-space:nowrap;" />
<coltemplate heading="Severity">
<span hideif="{Task_Status_ID}===3" style="color:{Severity_Color}; font-family:Webdings; font-size:10pt;">n</span><span hideif="{Task_Status_ID} == 3"> {Task_Severity}</span>
</coltemplate>
<col heading="Description" fld="Description" />
</cols>
<footer>
<gpdialog btnexit="Cancel" btnsubmitandclose="Save" title="Add New Call Log" url="Task_CRUD?userguid=#Model.UserGUID&manager=#Model.Manager&crud=c" callback="ggridReload('grdTaskSearchResults')" linkicon="/Icons/NewAddition.gif" />
</footer>
</ggrid>
That said, there's a couple of things in your code sample that I would like to look at in my own code. A potential improvement for us I think I can envisage in there. So in that regard, I thank you very much for your input.
No, my question is purely about the next step in the TagHelper story.
HtmlHelpers were written in c# and called in c#.
Taghelpers are written in c# and called in html markup.
Razor Components are written in html markup with some c# code inline/behind. However best implemented in Blazor using html markup. When called from within Razor pages, the call is made in c# code a little like HtmlHelpers were (a backward step for me).
What I would like to see somewhere in this story for the future, is a scenario wherby TagHelpers are written in html markup, with some c# code inline/behind, just like Razor components are now. And in use, the Taghelper called in markup as they are currently. I'm not suggesting that TagHelpers start to use c# on the client side. This is purely about how TagHelpers in their current guise and functionality... are written.
In essence, I am asking if anybody knows what the future holds for in terms of the next step for TagHelpers? Does this make sense?
I think a couple of years on, and I know the answer I was looking for. Moving forward at some point, blazor components are the next thing in line. I'm now considering converting all my taghelpers to blazor components in the future. At the moment, the only thing stopping me is the fact that you have to use some very verbose c# code within a razor page to use a blazor conponent. I'm hanging fire till they inevitably I feel, make it so you can use Html markup to consume blazor components within razor pages.
I place a button in a div tag, and when I run it, I only see the div container
<div style= "border-style:solid;border-width:1px; padding:5px; background-color:#ffffcc">
<asp:button ID = "refresh" runat ="server" OnClientClick="reloadPage()">
<script type="text/javascript">
function reloadPage(){
window.location.reload()
}
</script>
</asp:button>
</div>
the refresh button is nowhere can be found. Are there anything wrong with my code? I am new to MVC, please give me suggestions.
Why are you using asp controls in an MVC project -> use an HTML element.
Use a Form
<div>
#using (Html.BeginForm("Action", "Controller", FormMethod.Post))
{
<button type="submit">Submit</button>
}
</div>
Use a Button
<div>
<button onclick="DoSomeJavascript" >Submit</button>
</div>
MVC uses Controllers (Code Behind) and Views (Html) to create pages. To send data to or from a page you need to use View Models.
Maybe have a look at this handy guide: http://www.asp.net/mvc/overview/getting-started/introduction/getting-started
Your question states that you are new to MVC, yet you are trying to define a button from classic ASP.NET, which will not be processed by the Razor view engine used by MVC. Since you are just reloading the page you can do this with regular HTML buttons and Javascript. I'm not reloading the page here in this snippet, but that's irrelevant.
<div style="border-style:solid; border-width:1px; padding: 5px; background-color:#ffffcc">
<button id="refresh" onclick="reloadPage()">
Refresh Page
<script type="text/javascript">
function reloadPage() {
console.log("Reloaded")
//Reload page here
}
</script>
</button>
</div>
If you run this and click you should see the log message in your Javascript console.
I'm having a trouble while devolping my .net application.
I'm using the event OnTextChanged on a textbox to change the content in another Textbox, the first textbox has AutoPostBack="true", but when i write in it and click in another part, the page refreshes completely.
here is my ascx code:
<form id="Form1" runat="server">
Change text
<asp:TextBox id="txt1" runat="server" ontextchanged="ejemplo" autopostback="true"/>
<p><asp:Label id="lbl1" runat="server" /></p>
</form>
and the script in the same ascx page:
<script runat="server">
protected void ejemplo(object sender, EventArgs e)
{
lbl1.Text = "Changed";
}
</script>
I'm using MVC4,
Thanks for your answers.
EDIT:
here is a video of what is really happening:
http://remainedesign.com/video/asd.html
Life cycle of MVC and webforms both are different.
MVC is not about server controls.... viewstate... no page life cycle events in web form...
What is the 'page lifecycle' of an ASP.NET MVC page, compared to ASP.NET WebForms?
hope this helps..
Now coming to your point.
if you want to display something in the Textbox2 while entering a Value into the Textbox1 you have to use client side script, see example below
javascript
<script type="text/javascript" language="javascript">
function textCounter(field, field2, maxlimit) {
var countfield = document.getElementById(field2);
if (field.value.length > maxlimit) {
field.value = field.value.substring(0, maxlimit);
return false;
} else {
countfield.value = maxlimit - field.value.length;
}
}
</script>
Your Html page
<%using (Html.BeginForm("Index", "Account", FormMethod.Post)) // here index is a ActionName, Account is a controller name
{%>
<input type="text" id="textbox1" name="Message" onkeyup="textCounter(this,'textbox2',208)"/>
<input disabled maxlength="3" size="3" value="208" id="textbox2" /></label>
<input type="submit" value="Send" />
<%}%>
Here
textCounter() function on keyup event in textbox1 will display value in textbox2,
submit button will submit form which call action "index" on controller "Account",see below how action act
public class AccountController : Controller
{
[HttpPost]
public ActionResult index(FormCollection result)
{
string TextBoxValue=result["Message"];
return view("yourviewname");
}
}
please note,above example is solely for MVC project
i hope this example may help you..
the first textbox has AutoPostBack="true", but when i write in it and
click in another part, the page refreshes completely
That is exactly what AutoPostBack is for. If you click on another part, that's when you lose focus on the textbox and it will trigger a postback. If you need more proof then read this from MSDN:
Gets or sets a value that indicates whether an automatic postback to
the server occurs when the TextBox control loses focus.
I'm new to MVC and I'm implementing the Nerd Dinner MVC sample app in MS MVC2. I'm on step 10, "Ajax enabling RSVPs accepts". I've added the new RSVP controller and added the Register action method like so:
public class RSVPController : Controller
{
DinnerRepository dinnerRepository = new DinnerRepository();
//
// AJAX: /Dinners/RSVPForEvent/1
[Authorize, AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsUserRegistered(User.Identity.Name)) {
RSVP rsvp = new RSVP();
rsvp.AttendeeName = User.Identity.Name;
dinner.RSVPs.Add(rsvp);
dinnerRepository.Save();
}
return Content("Thanks - we'll see you there!");
}
}
I added the references to both Ajax script libraries and added the code below to the Details view as described in the article:
<div id="rsvpmsg">
<% if(Request.IsAuthenticated) { %>
<% if(Model.IsUserRegistered(Context.User.Identity.Name)) { %>
<p>You are registred for this event!</p>
<% } else { %>
<%= Ajax.ActionLink( "RSVP for this event",
"Register", "RSVP",
new { id=Model.DinnerID },
new AjaxOptions { UpdateTargetId="rsvpmsg"}) %>
<% } %>
<% } else { %>
Logon to RSVP for this event.
<% } %>
</div>
When I click the "RSVP for this event" link I get a 404 eror saying the resource cannot be found:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /NerdDinner/RSVP/Register/24
Version Information: Microsoft .NET Framework Version:2.0.50727.4200; ASP.NET Version:2.0.50727.4205
When I step into the code it is finding the Register action method correctly. After playing around with it I removed the "AcceptVerbs(HttpVerbs.Post)" from the constraint on the Register method, and it then worked. However it didn't reload the page it just displayed the "Thanks - we'll see you there" message on a new blank page. Looking at the html in the details page there is no Form submit taking place, so I'm wondering does the Ajax code need something more to make the call a Post? Is there a known issue with this part of the Nerd Dinner app? I think the app was written in MVC1 and I'm using MVC2 - does this make a diference?
TIA,
Ciaran
The PDF tutorial (versus the online HTML version) has typographic ANSI quote characters (0x94) rather than ASCII (0x22) in the HTML block of script elements. The correct block is shown below with all of the quote characters replaced.
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
Visual Studio will mark the JavaScript source files with the Warning green squiggles ("File not found") but not the type attributes so you may notice and correct the problem only for the source files. However, the type attributes will still be malformed and this will cause the scripts not to be loaded correctly in the browser.
Using the Chrome developer tools, I noticed that the scripts were not listed as Resources for the Details HTML page. Correcting the quote characters for the type attributes allowed the Register action to work as documented in the tutorial with no changes.
This portion of your action explains why you just get the "see you there" message:
return Content("Thanks - we'll see you there!");
That's all that's being returned.
The reason you were getting a 404 to begin with is the use of an actionlink:
Ajax.ActionLink(...
That will create a URL link, a GET not a POST, and the AcceptVerbs(HttpVerbs.Post) would have forced no match. You should submit a form to do a post:
using (Ajax.BeginForm("Controller", "Action", new AjaxOptions { UpdateTargetId = "f1" } )) { %>
<div id="f1">
<!-- form fields here -->
<input type="submit" />
</div>
<% } %>
As an additional comment to debugging issues with this problem, being a Java/JSF developer, I ran into a hard lesson that
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript" />
and
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
are processed differently. The first not working at all and the second working correctly.
This is the Details.cshtml used in MVC3. The problem with redirecting using GET, and not POST is similar.
<div id="rsvpmsg">
#if (Request.IsAuthenticated)
{
if (Model.IsUserRegistered(Context.User.Identity.Name))
{
<p>
You are registered for this event</p>
}
else
{
#Ajax.ActionLink("RSVP for this event",
"Register",
"RSVP",
new { id = Model.DinnerID },
new AjaxOptions { UpdateTargetId = "rsvpmsg", HttpMethod = "Post" })
}
}
else
{
<p>
Logon to RSVP for this event.</p>
}
</div>
#section JavaScript
{
<script src="#Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>;
<script src="#Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>;
}
Ok, so previously i have mentioned that i had the same problem, and it comes from the fact that MVC 3 uses unobtrusive JavaScript.
To make this work, you have 2 solutions, one is to disable Unobtrusive Javascript in your webconfig file:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Just set it to false, and during page build, javascript generated for the Action link will be normal inline javascript, that works fine, and results with something like this in HTML:
<a onclick="Sys.Mvc.AsyncHyperlink.handleClick(this, new Sys.UI.DomEvent(event),
{ insertionMode: Sys.Mvc.InsertionMode.replace, httpMethod: 'Post', updateTargetId: 'rsvpmsg' });" href="/RSVP/Register/13">RSVP for this event</a>
Second solution is more to my liking and it is just as simple. You just have to include additional javascript source file in your header:
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
#RenderSection("JavaScript",required:false)
</head>
The resulting javascript generated is unobtrusive, and results with this in HTML:
RSVP for this event
In both cases the resulting functionality is the same, and the second solution is "more in spirit" of new MVC 3.
Just in case it helps someone else, i had the problem using MVC 3 and it was because I had linked to the MS AJAX libraries and MVC 3 actually uses jQuery by default so I just needed to uncomment the links in my master page and it was fine.
To make an http post with Ajax.ActionLink , you'd have to do e.g. new AjaxOptions { UpdateTargetId="rsvpmsg",HttpMethod="POST"}
if you include those two in your site.master, it should be fine
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
I was trying to convert to MVC3/Razor as I worked through this example. I've been stuck on this exact same issue for at least 24 hours now...exact same symptoms. I tried everything on this page that I could understand or thought was relevant.
I didn't have the unobtrusive javascript mention in my web.config and was considering adding it with the "false" value thinking "true" might be the default. However, I was thinking it might screw something else up (among who knows what else).
I found the following tid-bit over on the wrox forum. If I add the following line of code to the second line of my RSVPStatus.cshtml partial view:
<script src="/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
Everything works as intended. I know Zak mentioned that line of code above (and a bunch of other stuff that lead me in the right direction), but I was using the partial view and haven't seen a head tag since I started messing with MVC. I know it's probably there somewhere, but all the smoke and mirrors of what is MS programming now, makes it harder to dissect and I probably would have gone down Zak's path at some point. So, +1 for him.
Anyway, hope this helps someone save a day.
I use this JavaScript code inside the head tag in order to populate the divs with a browse button so that users can upload images (swfupload).
<head>
...
<script type="text/javascript">
var swfu = function() {
return new SWFUpload({
// Backend Settings
// settings go here...
// Too long to display here
// Debug Settings
debug: false
});
}
window.onload = swfu;
</script>
</head>
....
<div id="swfu_container" style="margin: 0px 10px;">
<div>
<span id="spanButtonPlaceholder"></span>
</div>
<div id="divFileProgressContainer" style="height: 75px;"></div>
<div id="thumbnails"></div>
</div>
This works well, but the problem is when I try to put this code inside of a partial view. So far, I haven't be able to get this to work.
Is there anyone more experienced to the rescue?
Thank you
You can put your function like this:
<%= Ajax.ActionLink("YourAction",new AjaxOptions{ OnSuccess="swfu", UpdateTargetId = "spanButtonPlaceholder" }) %>
so your swfu function will be called if your update is successfull
The point of window.onload is to execute the given function once the page has finished... loading. That said, you should consider moving the onload to the bottom of the body. And I'm not the worlds biggest fan of keeping scripts in the head. :)
Partial views are rendered with Microsoft Ajax which does not evaluate JavaScript code. I would suggest looking at not using partial views in this case or look at other view engines like Spark....or put all required javascript in your parent view which kinda makes your code a bit sloppy