Html.EditorFor adding .textbox to element name - c#

I have a project which contains a simple form for collecting signup info. Recently I have been working to add localization to the project, as all of the text shown to the user was hardcoded. I'm not sure what changed, but for some reason, now when Razor renders an HTML element using the Html.EditorFor method that ends up being a textbox, the Name property of the element has ".textbox" appended to it.
This breaks the bindings, so that when I receive my model all of the text values are null. Here is an example of what I'm seeing, Razor code:
<div class="form-group" ng-class="{ 'has-error': validate && accountForm.FirstName.$invalid }">
#Html.LabelFor(m => m.FirstName, new { #class = #ViewBag.LabelCssRequired })
<div class="#ViewBag.TextboxCss">
#Html.EditorFor(m => m.FirstName, new { htmlAttributes = new { ng_model = "firstName" } })
</div>
</div>
and here is the rendered output:
<input class="text-box single-line form-control ng-valid-maxlength ng-not-empty ng-dirty ng-valid-parse ng-valid ng-valid-required ng-touched" id="FirstName_textbox" maxlength="100" name="FirstName.textbox" ng-model="firstName" required="required" type="text" value="">
It is also adding a "_textbox" to the id, but I'm not as concerned about that at the moment. For some reason, this only seems to be happening to input elements where the type is "text". I have another input generated with.EditorFor which has the type of email and it doesn't have any modifications to the name.
This behavior also seems to be restricted to Html.EditorFor, if I use.TextboxFor, it works fine.
I have been able to make the bindings work by explicitly setting the #Name property in Razor, but this only masks the symptom, and I would like to avoid having to do this for every text input on the site.
Has anyone seen this behavior before, or know of a fix?

By default, the TextBoxFor helper generates HTML using a built-in template. You can override the defaults by creating files in the project root\views\shared\editortemplates folder.
Therefore the problem can be caused by some custom template being present there. Normally, you need to check for files whose name Match either the datatype (such as string) or the control type (such as TextArea). If the corresponding model property has a UIHint attribute on it, a custom file specified in it can also come into play.

Related

How to render html code in #Html.TextBox asp .Net MVC?

Hi I'm creating MVC application and I'm using tinyMCE. Sometimes i need to change tinyMCE with simple TextBox field. I'm trying this with hide and show. At the begging I'm showing TextArea and hidding TextBox, but when user click convert tinyMCE to simple textBox field, I'm hidding textArea and showing TextBox.
This is my tinyMCE field
#Html.TextAreaFor(model => model.supTitle, new { htmlAttributes = new { #class = "form-control" } })
and this is simple TextBox
#Html.TextBoxFor(model => model.supTitle, new { htmlAttributes = new { #class = "form-control" } })
but when I'm using TextBoxFor I have something like this
<p> some text</p>
but I want only some text to be displayed without <p> tags.
Also when I save the changes only the changes from TextArea are saves into database.
If the value stored in the model.supTitle property contains Html as a string you would have to parse out the html before rendering the value to a standard input[type=text].
Only the first value is persisted to the database because both form elements have the same name, when the form is posted both values will be sent in the Http Post but the MVC model binding will only map the first form value to the model (which in this case is the text area).
Hiding & showing a html element does not prevent the value of the element from being posted in a form post, you would need to either remove the element from the DOM altogether or change the element name so that it is not bound by the model binder.
Try using this in your view
#Html.Raw(Model.YourTinyMCEContent);

Applying css class using Html.DisplayFor inside razor view

Inside razor view I used model for rendering label like
#Html.LabelFor(model => model.MyName, htmlAttributes: new { #class = "control-label col-md-6" })
and now I want to use it's value instead of data annotation attr. value so I tried with DisplayFor like
#Html.DisplayFor(model => model.MyName, new { #class = "control-label col-md-6" })
this css class control-label col-md-6 is not apply.
Why?
The difference is that #Html.LabelFor helper function renders a <label></label> tag, and the #Html.DisplayFor helper function does not render any html tag, instead it renders plain text. For example the following code:
#Html.DisplayFor(model => model.MyName, new { #class = "control-label col-md-6" })
returns raw text:
Martin
considering that MyName had the value "Martin". And the code:
#Html.LabelFor(model => model.MyName, htmlAttributes: new { #class = "control-label col-md-6" })
will return:
<label class="control-label col-md-6">Martin</label>
Consider the difference.
Use following (if you want to use #Html.DisplayFor):
<span class"control-label col-md-6">#Html.DisplayFor(model => model.MyName)</span>
DisplayFor doesn't work like the other *For helpers. Like EditorFor, it's what's referred to as a "templated helper". In other words, what it renders is controlled by a template that can be modified. Importantly, for both of these methods, if you look up their documentation in MSDN, you'll see that the parameter that would normal correspond to htmlAttributes with the other helpers, instead refers to additionalViewData with these two. This is because, again, their output is controlled by essentially views, which take ViewData.
Additionally, with DisplayFor in particular, the default templates pretty much just output the value, with no HTML. If you pass a string property, for example, the output will be the value of that string and nothing else. Therefore, there's nothing to tie the HTML attributes to, even if you could pass them in.
If you want to do what you're trying to do, you'd have to create custom display templates. This can be done by adding views named after types (e.g. String, Boolean, Byte etc.) or members of the DataType enum (CreditCard, EmailAddress etc.), to Views\Shared\DisplayTemplates. For example, if you created a view at Views\Shared\DisplayTemplates\String.cshtml, then when you called DisplayFor with a property of type string, that view would be utilized to render it. You could then wrap the value that would otherwise be just output directly in some HTML of your choice and utilize ViewData to apply the appropriate HTML attributes. For example:
<span class="#ViewData["class"]">#ViewData.TemplateInfo.FormattedModelValue</span>
.NET Core 2.2 Razor Pages Resize Checkboxes
Late to the game here but needed to make check-boxes huge compared to how Razor Template displays them. Because I wanted user to see if it was checked or not.
I tried above stuff, didn't work. So I used Chrome Developer Tool to look at what the page was rendering and it showed this for the checkbox:
input[type="radio"], input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
And I was going to go find it in the CSS file because I could use all check-boxes to be bigger. However, it said it was located here:
reboot.scss:373
Now, I swear it referenced a different scss file when I first opened in developer. But since it looked like Greek to me, a code slob, I just decided to put this (after trying it in style above) at the top of my Razor Page. Notice I just cloned the hidden style above and just added width and height:
<style>
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
width: 40px;
height:40px;
}
</style>
Now, Here is the Razor control I was displaying. It ends up as a checkbox in html at end, but I believe Razor Page is smart enough to know it was a True/False field and showed it as a text box. But. . . not before it applied the sizing I added!! Hope this helps someone.
<td>
#Html.DisplayFor(modelItem => item.Moderated)
</td>

How do you access the model in an EditorFor template?

How do you access the model in an ASP.NET MVC Editor Template? For example if the parent view contains say:
#Html.EditorFor(x => x.Surname)
Then inside Views/Shared/EditorTemplates/String.cshtml we have:
#model String
<div class="field">
#Html.LabelFor(x => x)
#Html.TextBoxFor(x => x)
#Model.Length
</div>
This fails at #Model.Length because Model is null, although the LabelFor and TextBoxFor render the correct Surname properties.
When Html.DisplayFor with the equivalent template file is used, Model does contain the given string value.
Creating a Editor Template for something as broad as String could have unintended consequences, since you will very likely have many EditorFor(x => x.StringValue)s in your code that you don't want this Editor Template to apply to.
It's likely that you have another EditorFor that is causing the nullref exception here.

Creating a new object in a view which passes IEnumerable object

I'm having a bit of pain trying to solve how can I create a new object when I'm passing to my view a IEnumerable.I'm having the creation of the new item in a modal jquery-ui window on the same page.
<div class="form-group">
#Html.LabelFor(model => model.Title)
<div class="col-md-10">
#Html.EditorFor( model =>model.Title)
#Html.ValidationMessageFor(model => model.Title, "Please choose a title that is not empty or less than 3 symbols")
</div>
</div>
So this is the code snippet that I'm trying to implement in the main view from where my js gets the information,but since my model is a collection I cannot access the editor options in my razor view.
This is a part of my js file where I get the values of the items inside the input boxes listed above which do NOT work becase I'm operating on a collection.I cannot change the model so I need a shortcut through it.
$.ajax({
url: "/Course/Create/",
type: "POST",
data:{
Title: $("#itemTitle").val(),
CourseDescription: $("#itemDescription").val(),
CourseCategory: $("#itemCategory").val()
},
You should pass a View Model that will contain both the IEnumerable collection + an object that you would like to submit (with Title, Description and Category properties).
In case you cannot change the model that you are passing to the view you should not use Html.EditorFor but simply Html.Editor (the same applies to Html.LabelFor and other Html extensions that you use there).
Of course you then need to pass appropriate name parameter ( e.g. "itemTitle") to these extensions that will comply with the ones used in the JS code.

MVC Disable EditFor automatic-fill

I have recently started using MVC, and stumbled upon a problem.
So, I have a user model, which contains some variables like ID, UserName, Password, and they all correspont do a database table, which MVC completely handles.
I now have a password edit page, with a password text box, and a confirm password text box, like this:
<div class="editor-label">
#Html.LabelFor(model => model.Password)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
#Html.Password("passwordConfirmation")
</div>
So, that works out all fine, it has 2 text boxes next to eachother.
Now here's my problem: I don't want the first password text box to be automatically filled with the data from the "Password" variable that is in the model passed along with the page.
Ofcourse there's the "hackish" way of doing it, where you just create a regular password box, and then get it's value later (#Html.Password("password")),
but I want to know if there's an official way of telling MVC NOT to auto-fill in the text/password box.
You could try applying the autocomplete="off" attribute to your password field:
#Html.PasswordFor(x => x.PasswordConfirmation, new { autocomplete = "off" })
Note that this is a non-standard attribute and might break HTML validation but most browsers respect it.
Also you should make sure that you are not setting any value on your view model for the PasswordConfirmation property inside the controller action.

Categories

Resources