I want to create something like a user control in my MVC 4 project. I have followed the instructions in this article so i have added the App_Code folder(it was not initially there) in the project. Inside i have put a file
VDRazorHelpers.cshtml
Inside that file i have my code which is actually a static html table(i would add dynamic values later):
#helper PropertySummary(){
<tr>
<td width="210" align="center" colspan="2">
<img src="http://www.mysite.com/images/BG1.JPG" width="210" height="140" />
</td>
</tr>
}
Then in my view i try to access that helper writing:
#VDRazorHelpers.PropertySummary
but this doesn't seem to be available.
I know the article i mentioned is for MVC3. Has it change? What would be the proper way of having custom reusable html parts in MVC4?
Here is the screenshot of the intellisense:
I would be more inclined to use a partial view which you could place in the shared views folder then call passing the model you wish to render with that view:
#Html.Partial("propertySummary", property)
Just a thought
Partial Views are the closest to an analogue of a Web Forms User Control in MVC. They encapsulate HTML that can be reused on other views or returned directly from action methods, which is handy for AJAX calls that need to fetch some HTML. Big difference in MVC is that the Partial Views don't have the ViewState of a User Control in Web Forms, nor does anything, it's gone, and good riddance as far as I'm concerned. HTML Helpers could also be considered close to User Controls however they are completely based in code and generate HTML whereas Partial Views are the markup.
Related
I've got an ASP.NET Core MVC Web App, and one of my Views has too much HTML, causing it to look messy and difficult to find stuff, is there a way to extract some of the HTML (for example a certain div) to a different .cshtml file that I can then include in the View?
Here is a partial view sample:
Shared/partial1.cshtml:
<h1>partial1</h1>
Test.cshtml:
<partial name="partial1" />
Or:
#await Html.PartialAsync("partial1.cshtml")
result:
You can also use View Component,here is an official doc.
I have just gotten started with ASP.NET MVC 5 (C#) and have been a little confused by the HTML helpers.
#using (Html.BeginForm("Add", "Song"))
I understand how this can be helpful, but feel that for people who do not know Razor/C#, that this will be a steep learning curve if not properly exposed. I am also aware of the Tag Helpers that are available and like what I see so far.
<form asp-action="Add" asp-controller="Song">
To me, this seems more appropriate, as it means that people who do not understand Razor syntax will be able to more easily read and understand what is happening, as it bears much more similarity to "normal" HTML. That being said, changing each page to use Tag Helpers seems monotonous and unnecessary.
I have recently found the CodeTemplate files, and included them in my project with the intention of adding the Tag Helpers in the template files. However, I soon realized that most Tag Helpers need a specific Controller or whatever to fill out the element attributes. Obviously, this Controller/whatever will change dynamically depending on which Controller/whatever prompted the creation of the View. If I hardcode asp-controller="Song" and then I try to create an Album View from this CodeTemplate, I obviously will have used the wrong controller.
Is there a way to access the dynamic property of whatever Controller, Link, etc called the View? In other words, is there someway of doing this in the CodeTemplate, where This is the Controller/whatever that constructs the View from the modified CodeTemplate?
<form asp-action="This.Action" asp-controller="This.Controller">
Example:
If I had <form asp-action="This.Action" asp-controller="This.Controller"> in my CodeTemplate in all Views, and then created the Views from different Controllers:
Song Controller
Create View - <form asp-action="Add" asp-controller="Song">
Update View - <form asp-action="Edit" asp-controller="Song">
Album Controller
Create View - <form asp-action="Add" asp-controller="Album">
Update View - <form asp-action="Edit" asp-controller="Album">
Is this possible at all? Or am I completely off? Let me know! Thanks!
You can try the solution I found here.
<form asp-controller="#this.ViewContext.RouteData.Values["controller"].ToString())"
asp-action="#this.ViewContext.RouteData.Values["action"].ToString())">
Simple question;
When are Custom HTML Helpers supposed to be used. Are we supposed (as intended by the developers of MVC) to implement an Extention method for all tags/logic that are reused across the views?
I'm curious about this, as we currently have a medium sized project that needs to be refactored. Alot of different interns have been working on this, and its time to do a cleanup.
Use Html Helper for rendering an Html Element. That element may contain inner elements, but your helper should mean the outermost element. Let me give you an example. Say, you want to render an Image button with some specific attributes so that your image button will look like this:
<button title="my button" onclick="onClickFunctionName()">
<img src="...." />
</button>
So, an Html Helper with following signature can be very useful:
#Html.ImageButton(title:"my button", onclickFunctionName:"onClickFunctionName", imageSource:"....")
Same like an image button, you can encapsulate creating a Table using Html Helper.
If you want to encapsulate a piece of html markup for some partial layout, then you should use Partial Views. For example, a Partial View can be used for rendering Login box with User name and Password and a Remember Me Checkbox. In this case, an HTML Helper wont be a good idea to use.
In situations where you want your links to work with your routing configurations. You use HTML property. It's instance of IHtmlHelper which contains methods for generating snippets of html. You could type them by hand, but this html property has a logic behind the scenes to use some metadata or configurations in your application. Also, HTML Helpers know built-in conventions in the MVC framework.
I am currently working on converting an existing webforms application to MVC and am not sure how to design one of the pages. The existing page is 2500 lines of code, and is responsible for displaying several different views of the same information. The following example is just a small piece of this page (a toolbar), but I'm not sure what the best approach is to avoid duplicating code.
Administrator view toolbar:
Save, PDF, Print, Spell Check, Administrative Documents, Employee View Toggle
Manager view of toolbar:
Save, PDF, Print, Spell Check, Employee View Toggle
Employee view of toolbar:
Save, PDF, Print, Spell Check
I have split the application into three different views. They use the same partial views to render the content of the page, but currently each view has it's own copy of the toolbar. So the HTML elements for Save, PDF, Print and Spell Check are duplicated in each of the views. It would be ideal to have a partial view to render the toolbar, but in order to do that I would need to put some sort of logic in the view to determine if it should show the Employee View Toggle link or the Administrative Documents.
I have also ran into similar problems while developing other new pages. Initially the requirements for different pages have the same element on them that we split into a partial view. After testing and adding more functionality, eventually the partial view needs to be slightly different on each of the pages. Usually it's just the visibility of the certain controls, but eventually the partial views end up having a bunch of logic in them to check several things to determine if something should be shown.
What is the best approach for dealing with slightly different views where most of the elements are the same?
If it's just an issue of permissions showing or hiding different parts of the same control/partial view/whatever, I would say just write one and have some code in it to check permissions and conditionally render or don't render various parts. Something like this:
<%# Control Language="C#" %>
This is the toolbar!!
<div class="fake-css-class">
<%:Html.ActionLink("Save", "Save") %>
<%:Html.ActionLink("PDF", "Pdf") %>
<%:Html.ActionLink("Spell Check", "SpellCheck") %>
<% if (CurrentUser.IsInRole("Admin") { %>
<%: Html.ActionLink("Administrative Documents", "AdminDocs") %>
<%} %>
<% if (CurrentUser.IsInRole("Admin") || CurrentUser.IsInRole("Manager"){
%>
<%: Html.ActionLink("Employee View Toggle", "EmpView") %>
<%} %>
</div>
<br />
<br />
EDIT:
When the logic gets more complicated, add functions to your security code so that you can separate all the logic out into your model/controller and in the view you're making a single function call. For example something like this:
public bool Authorize(string controllerName, string actionName) {
bool authorize = false;
foreach(var permission in this.permissions) {
if (permission.Matches(controllerName, actionName)) {
authorize = permission.Affirmative;
}
}
return authorize;
}
This way you could have the code outside of the view and simply a single line of code in the view. The above code is just taken out of my current project and used as an example, but you can write whatever complicated logic and put it out in the model or controller so your view stays clean and you aren't putting business logic in there.
So currently in our code, we have a bunch of classes around accessing roles and permissions for specific users logged into the web application. This is built fine, and works well. However, a certain requirement that has come up now is not only the ability to restrict certain pages (whole views) to certain permissions, but also specific fields on those views. So you might have the ability to see a view, but you might only have a permission that lets you see certain fields on that page.
We generate most of our fields using HTML Helpers with in ASP.NET/C#. For example here is one that we need to block/show depending on a permission:
<%= Html.CheckBoxFor(m => m.Current, new { #class = "economicTextBox", propertyName = "Current", onchange = "UseCurrent();UpdateField(this);" })%>
My first thought was just to play the check for permissions in similar embedded C# code right before that and put the HTML Helper in an "if" statement, so it would only render if the user had the permission. I second guessed myself when I saw the front end getting very bloated with all of these statements in my mind, and thought there might be a better way to do it.
Can any of you guys recommend anything? Thanks.
Have the user permissions as a separate module of the model. Create partial views which contain the blocks of code that you want to show/hide. Pass the module to the partial view, and have the view hold the logic for what to show.
This should mean you can create one block of logic in your partial view, with the decision being some basic ifs or switches and the mark up for displaying it more distinct and manageable.
So for example, let's say you make a permissions model that all your page models inherit, thus ensuring you can pass around the same permissions to all pages. You can then call a view and pass it the model like this:
<%Html.RenderPartial("Widgets/NavigationUserControl"); %>
This will hold the mark up and logic for user navigation. Inside this partial view you'd have it inherit your permissions object:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<WebApp.Web.Models.Permissions>" %>
And then you can do your more basic logic in the markup, or have a html helper do the grunt work and return some enums/properties for more basic code to do decision on. For example;
<%
if (Model.User.IsAdmin)
{
%>
...html...
<%
}
else
{
%>
...html...
<%
}
%>
My first thought was just to play the
check for permissions in similar
embedded C# code right before that and
put the HTML Helper in an "if"
statement, so it would only render if
the user had the permission. I second
guessed myself when I saw the front
end getting very bloated with all of
these statements in my mind, and
thought there might be a better way to
do it.
Put the if inside your Html Helper and pass to the helper function what data you need to perform the conditional check.
View:
<body>
<p>text</p>
<%: Html.PermissionControlledFieldOne(someUserData, otherData) %>
Helper:
public HtmlString PermissionControlledFieldOne(....) {
if (performSecurityCheck(someUserData, otherData)) {
// .. render partial or build html or whatever you need
}