I'm just learning how to do ASP MVC. All of the tutorials I see use a combination of Html.LabelFor and the DisplayAttribute. Personally, I'm not a big fan of adding these kinds of annotations to my model objects and I'd like to know if there is an accepted alternative. I thought this might be a place for something like Knockout or Backbone, but I'm so new to this stuff that I'm having difficulty wrapping my brain around the different pieces.
I know this has probably already been asked and answered; I can't even figure out how to google it :(
Thanks in advance
you can skip Data Annotations
you can write
<label for='#(var1)'>#Name</label>
or
<label for='name1'>Text</label>
or
Html.Label("ControlName", "Name")
or
Html.LabelFor with data anot.
any of this will be correct
also using helpers with lamda expressions (Html.LabelFor) is much slower than Html.Label or simple html code <label for='#(var1)'>#Name</label>
It is true for all asp.net mvc html helpers
Related
So I'm converting a WebForms application into ASP.NET MVC 4 and I would like to make sure that I'm making correct coding choices and assumptions.
1). Is the MVC equivalent of a user control a partial view?
2). In an aspx page you have a control like
<asp:Label id="X" runat="server">
with the following code in the code behind:
X.Visible = some_condition ? true : false;
Ok so, for MVC is this code equivalent?
View:
<label id="X" style="display: #Model.IsViewable">
Model:
IsViewable = some_condition ? "inline-block" : "none";
1.) Well, kinda, sorta, but no not really. Very different things - a detailed explanation would be lengthy.
2.) Equivalent maybe, but not really a good thing to do. Your model should contain data only. But yes, you can use this data in your razor views to conditionally do things including show or not show things. However, putting the css strings straight into your model data is klunky at best as well as it's usually a good idea to avoid inline styles whenever possible. IsViewable as a boolean would be better, and you can still handle showing or hiding elements (in a different way).
I'm using AngularJS in my MVC application and trying to use the best of both worlds. I really like how you can in MVC set up your validation logic in your viewmodels and generate client side validation with jQuery validation in your razor views with little effort. I use AngularJS to get the SPA behavior with routing etc, but when I create a razor view that I use to inject into a page with:
<div data-ng-view="data-ng-view"></div>
then the jQuery validation stops working, even though the script files is references on the page where the view is injected. See below for my razor view:
#model BandViewModel
<div data-ng-controller="App.BandCreateCtrl">
<form name="startBandForm">
#Html.ValidationSummary(true)
<br />
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name, new { data_ng_model = "band.Name" })
#Html.ValidationMessageFor(m => m.Name)
<br/>
<input data-ng-disabled="startBandForm.$invalid" type="submit" data-ng-click="createBand(band)" value="Create"/>
</form>
</div>
First of all, IMO using Razor to render your templates is fraught with peril, at best. Generally you want to use static HTML for your page and directive templates, and then retrieve and post data as AJAX to your API. The ASP.NET web API is really good at this, actually. If your underlying model has validation, then bad web API calls will throw an exception, which you can catch in your $http or $resource handler and show to the user. Mixing standard HTTP form posts with AngularJS will be... difficult.
To achieve what you want, I think someone (not me) would have to write the AngularJS equivalent to jQuery Unobtrusive Validation library, which itself is using the jQuery Validate plugin. Not trivial. I personally don't see drop-in Angular validation happening soon, especially since it has more to do with markup and less to do with a JS configuration object.
Possibly you could re-initialize the validation when the view has finished loading using the $viewContentLoaded event. But please don't.
It pains me that everywhere I've looked we get the same replies: "HTML should just be a template". Perhaps, but I'm just not ready to delegate everything to JavaScript
Instead of using the anonymous object for passing the HTML attributes, try using the Dictionary
#Html.TextBoxFor(m => m.Name, new Dictionary<string, object>(){{ "data_ng_model", "band.Name" }})
Make sure is
Dictionary<string, object>
And not
Dictionary<string, string>
Otherwise the constructor will confuse it for
object HtmlAttribute
Not as pretty though... but it works for the most part.
Lastly, take in mind that if you include AngularJS after jQuery, then it will use jQuery for selectors.
To anyone still looking for a solution to this problem , there is a simple way to make it work.
var currForm = $("#myForm");
currForm.removeData("validator");
currForm.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(currForm);
currForm.validate();
You could put this code in $viewContentLoaded or other places which are relevant in your code.
While I understand some of the views here which discourage MVC views being used as a templates for your Angular code. My reason being its not not a natural way of doing things in angular and hence there are chances that you will run into issues like this one. But if you benefit from using MVC views as templates its not a path to hell. IT works and can benefit you as well. I have 2 use cases in my project where using MVC views make a lot of sense.
My project actually has a requirement where a client can turn of the required validation on certain field , for this I use the MVC custom data annotation validator which allows me to add or remove the data annotation at the time of rendering the view using a single class , if you were to build the same flexibility in angular , you would have to write a lot more code. So MVC views work great here for me as Custom Data Annotations are triggerd by the DisplayFor and EditorFor helpers
We are heavily invested in Internationalization and while angular is great at other stuff internationalization is not its strong suite ( at the time of writing this atleast )I still feel the internationalization support in MVC with .RESX works great and has been here long . This again uses the data annotation power of the DisplayAttribute.
TLDR : MVC views as templates may give you a few unexpected problems but are worth it if you are really using the full power of the data annotation pipeline created by Microsoft.
Hopefully someone comes up with a Angular HTML Helpers library in the future this would be much simpler.
Maybe using Angular for validation can be less painful than you think. Using a couple of custom directives, you could easily get something quite close to Razor with markup as simple as:
<validated-input name=username display="User Name" ng-model=model.username required</validated-input>
Check out my sample here and its inspiration here. It only implements required and number at the moment, but customizing it should be easy.
You can use ngval library. It brings data annotations to client side as angularjs validation directives.
i don't like auto-generated code so i made a decision to never use Asp.net MVC's Html Helpers, but i face a problem when it comes to save the value of an input after validation failed, so the value is saved when i use
#Html.TextBoxFor(m=>m.Name)
but it doesn't save the value when i write
<input type="text" name="Name"/>
so how can i have the same thing without using TextBoxFor Helper, and what does this helper do, that i haven't
i don't like auto-generated code so i made a decision to never use Asp.net MVC's Html Helpers
You are going to have a hell hard time doing ASP.NET MVC development if you do not use helpers and I am afraid that you will not get very far. You will struggle not only with things like setting values for input fields but also emitting HTML5 data-* attributes on your input fields for things like unobtrusive client side validation, all things that are automatically handled by HTML helpers.
You could always perform the following pornography in your view if you find that more readable:
<input type="text" name="Name" value="#Html.Raw(HttpUtility.HtmlAttributeEncode(Model != null ? Model.Name : ""))" />
But I don't know why I kinda prefer writing #Html.TextBoxFor(m => m.Name). I don't know, maybe it's just a matter of personal preference.
But to answer your question, you can do ASP.NET MVC without helpers. It's just that you might find that a pretty disagreeable experience.
Is there some magic existing code in MVC 2 to Html.Encode() strings and allow certain html markup, like paragraph marks and breaks? (coming from a Linq to SQL database field)
A horrible code example to achieve the effect:
Html.Encode(Model.fieldName).Replace("<br />", "<br />")
What would be really nice is to overload something and pass to it an array (or object) full of allowed html tags.
It's not a good idea to create your own whitelist based on regular expressions because you'll likely inadvertently open a security hole for XSS.
From Sanderson's book "Pro ASP.NET MVC3 Framework": "...The only viable mitigation is strict, whitelist-based filtering: use a library like the HTML Agility Pack to ensure the user-supplied markup contains only the tags that you explicitly allow."
Sanderson goes on to supply a link to a site that demonstrates a broad range of XSS techniques that you'd have to test for if you use the regex approach. Check out http://ha.ckers.org/xss.html
There is nothing built in to ASP.NET or MVC for this, but it's not that hard to write your own whitelist-based one with regular expressions and so on. Here's one that Jeff wrote, though it's pretty rough around the edges...
I can't think of anything off the bat but I guess you could write an extension method that allows you to add a paremeter/list of items to allow.
Html.Encode(Mode.fieldName, List<items> Myitems);
It could modify the allowable tags into < etc and then encodes the rest like normal.
Is there a specific reason why I should be using the Html.CheckBox, Html.TextBox, etc methods instead of just manually writing the HTML?
<%= Html.TextBox("uri") %>
renders the following HTML
<input type="text" value="" name="uri" id="uri"/>
It guess it saves you a few key strokes but other than that. Is there a specific reason why I should go out of my way to use the HtmlHelpers whenever possible or is it just a preference thing?
Another benefit is that if your ViewData contains a value matching the name of the field it will be populated.
e.g.
ViewData["FirstName"] = "Joe Bloggs";
<%=Html.TextBox("FirstName") %>
will render
<input type="text" value="Joe Bloggs" id="FirstName" />
There are huge benefits:
It has overloaded methods to pre-populate the values (formatted, and safe for HTML) just like the ViewState.
It allows built in support for the Validation features of MVC.
It allows you to override the rendering by providing your own DLL for changing the rendering (a sort of "Controller Adapter" type methodology).
It leads to the idea of building your own "controls" : http://www.singingeels.com/Articles/Building_Custom_ASPNET_MVC_Controls.aspx
One thing is for consistency...I for one always forget the name attribute. Plus, you can extend the functions for your own projects. They're not called helpers for nothing!
The upside to using an abstraction layer is future proofing your code in a pluggable way. Maybe today, you create HTML 4 pages but tomorrow you want to create XHTML pages or XAML or XUL. That's a lot of changes if you just hard code the tags everywhere, especially if you've got hundreds of pages. If everything is calling this library, then all you've got to do is rewrite the library. The downside is that it is usually considered to be slightly less readable by humans. So, it most probably increases the cognitive demand on your maintenance programmers. These advantages and disadvantages really have nothing to do with MVC.
It actually auto populates your textbox based upon first your ViewData.Model.uri and second by ViewData["uri"]. Doing it manually you'd need to do <input value="<%Html.Encode(ViewData.Model.Uri"%>" />
I haven't been doing MVC too long, but I've already written some extension methods to generate menu tabs based on Html.ActionLink. It allows me to be consistent with my usage and, if I decide to change how my CSS menus work, only modify a single method to output the new tab format.
The other use that I have made of them is in conditional output using ViewData to supply values to the controls.