Putting form validation on html controls in razor engine - c#

I have been facing an issue of putting form validation on html controls any one guide me how to resolve this issue?
My HTML Field In something.cshtml
<input type="text" id="AccidentDate" name="AccidentDate" />
#Html.ValidationMessage("AccidentDate")
Controller code:
[HttpPost]
[AllowAnonymous]
public ActionResult Index(Models.c objC)
{
if (String.IsNullOrEmpty(objC.AccidentDate))
{
ModelState.AddModelError("AccidentDate", "*");
}
return View(objClaimant);
}
Please note validationMessage does raise error in the form of * in-front of that input field but my requirement is to highlight that input field as red.
MOST IMPORTANT I KNOW IF I USE:
#Html.TextBox("AccidentDate", Model.AccidentDate); it works perfectly but using this is not my requirement.
finally, i am looking to make html input field red through any other way, if validation message is raised.
any help would be appreciated.

Ok, so rather than just commenting I figured I'd try and help. So I'm presuming you want to use the unobtrusive validation engine
So if you do
#Html.TextBox("AccidentDate", Model.AccidentDate);
and view source you'll see something like:
<input data-val="true" data-val-required="The AccidentDate field is required."
id="AccidentDate" name="AccidentDate" type="text" value="">
So the important thing to notice are the data-val attributes. These basically tell the unobtrusive engine, "this field needs to be validated and this is how and what to display if it fails"
So to do this without #Html.TextBox which does all this for you, you'll need to create these attributes yourself in your HTML.
Quick an dirty solution, put your #HTML.TextBox in, run your code cut&paste the HTML. May not be what you want?
Edit
you want the required validation, so the above data-val="true" data-val-required="The AccidentDate field is required." attributes are what you need, obviously substituting your own error message
so:
<input type="text" id="AccidentDate" name="AccidentDate"
data-val="true" data-val-required="The AccidentDate field is required." />
#Html.ValidationMessage("AccidentDate")
Css Class
The Css class should be being applied. The relevant piece of code is:
function onError(error, inputElement) { // 'this' is the form element
var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;
container.removeClass("field-validation-valid").addClass("field-validation-error");
error.data("unobtrusiveContainer", container);
if (replace) {
container.empty();
error.removeClass("input-validation-error").appendTo(container);
}
else {
error.hide();
}
}
inside the jquery.validate.unobtrusive.js. confirm your referencing this js file and see if the above code is hit?

Related

C# get value from hidden input

I've been trying to get the value from a hidden input and innertext from a span on a website (note that I don't have access to edit the HTML code).
Code from website:
<input type="hidden" name="hidv" value="1582912961">
<span class="valo">0.888</span>
I could use a code similar to this but don't know the correct use of it:
label5.Text = webBrowser2.Document.GetElementById("hidv").InnerText;
label6.Text = webBrowser2.Document.GetElementById("valo").InnerText;
First I'd put an ID on the input tag
<input id="myId" type="hidden" name="hidv" value="1582912961">
Then you could use JS, jQuery, etc, to select the value.
$('#myId').val();
$('input[name=hidv]').val()
also just a note Document.GetElementById requires an Id. Otherwise, you could've done Document.GetElementsByClassName("valo") if you wanted to use the class name instead of an Id attribute.

textarea asp-for doesn't display property

I've been working on a small school project and decided to use .net core (MVC) for the first time. I have a small button I can click which executes the "ipconfig" command in the background and displays the output in a text area. At first my team partner used only a
public string Result;
in ViewModel for the view. In the view it's displayed via
<textarea asp-for="Result"></textarea>
So I decided to make it into a property with default get and set:
public string Result { get; set; }
But when I do that, the output doesn't show up in the textarea if I keep the same approach in the view as my team member did when he used a field instead of a property. Instead I have to do it like this to get it to show up in the textarea:
<textarea>#Model.Result</textarea>
Now I'm asking myself why this happens. Can't I display Properties with asp-for? And what would be better to use, a field or a property as Result?
Many thanks in advance!
In my case this behavior was happening because I did not have a separate closing tag on my textarea. I know your example above has it when using the asp-for method, but in case that was a copy/paste error, you may want to look at that again.
<textarea asp-for="Message" type="text" class="form-control" rows="5" id="MessageInputField" autofocus></textarea>
As opposed to:
<textarea asp-for="Message" type="text" class="form-control" rows="5" id="MessageInputField" autofocus />
This is incredibly annoying 'gotcha' like behavior in my opinion. And maybe if someone wants to tell me why it isn't, then please enlighten me, I'm always willing to learn.
You should actually be using properties, and if <textarea>#Model.Result</textarea> works, <textarea asp-for="Result"></textarea> should as well. The only reason it wouldn't is if the ModelState has a different value for Result (as the latter form actually uses ModelState, whereas the former is obviously using Model directly).
ModelState is composed of values from Request, ViewData/ViewBag, and finally Model, so for example, if you were to do something like ViewBag.Result = String.Empty, that would actually override the value from Model in ModelState.
There's no enough code here to truly diagnose the exact issue, but I would look for other places you might be using "result" (case-insensitive). If you're accepting that as a request param or setting a ViewBag member, etc. that's your problem.
I find this is a bit weird in .Net Core 6, when I want two-way binding - ie displaying the result
With asp-for I have to self close the tag AND add the additional textarea close tag to get the result displayed.
<textarea asp-for="Result" />#Model.Result</textarea>
This works but is not syntactically correct.
Without the self-close tag, the result was not being display
<textarea asp-for="Result">#Model.Result</textarea> #*Does not display the value*#
For display only, this is more correct
<textarea>#Model.Result</textarea>

Posting dynamically added list items to controller

I have a partialview that has a viewmodel containing a form with only email and name input. I post this data with jquery ajax to my controller to do some validation. My controller is a PartialViewResult method, see:
[HttpPost]
public PartialViewResult InviteUser(InviteEmailViewModel item)
{
return PartialView("_InvitedUsers", item);
}
My jquery adds the result of this method to the DOM, since ive uses hiddenfor i get inputs like:
<input data-val="true" data-val-required="Name is required." id="Name" name="Name" type="hidden" value="test">
<input data-val="true" data-val-regex="Invalid Email Address" data-val-regex-pattern="^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+#((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$" data-val-required="Email Address is required." id="Email" name="Email" type="hidden" value="test#test.test">
The problem with this is that my ViewModel contains a List but after posting the form with the added partialviews the List is Null. Ive tested with hardcoded input fields like:
<input data-val="true" data-val-required="Name is required." id="Name" name="InviteEmailViewModel[0].Name" type="hidden" value="test">
and that does seem to work. How do i make MVC generate hidden fields like in my hardcoded example?
To answer your Q:
To include hidden fields in the post, these need to 'survive' the create-in-controller-survive-the-post, if the field isn't in the form, then it won't be posted back to the controller, regardless if it's been created before in the controller.
Add the hidden field anywhere within the form so that it's posted back. So when it's created it'll have a container and will therefor be present on post.
IE:
#Html.HiddenFor(m => m.myHiddenField)
#Html.TextBoxFor(m => m.displayedField, new { #class = "NotHidden" })
What it could be:
If I'm understanding correctly you've got a ViewModel with a List, which is the model of the partial, which you want to add dynamically to your VM and bind on post.
To add items to a list dynamically, without them going null, you'll need to use BeginCollectionItem, which handles the hidden GUID issue for you.
I had similar issues and asked two questions which have solutions here and here, the latter is a problem with accessing a property two models down, but shows more complete code.
The issues that you've got are with the GUID. It doesn't go back through the post without help.
What you need is a prefix in the name/id so that the object can be properly assigned to its model when you post.
BeginCollectionItem will sort this out for you - which you can get 'stock' via typing Install-Package BeginCollectionItem in Package Manager Console in Visual Studio, check out this guide - here or you can download the file/whole thing and add it to your project manually by going to GitHub here
name="viewmodel[f7d8d024-5bb6-451d-87e3-fd3e3b8c1bba].listOfObjects[d5c08a43-f65e-46d1-b224-148225599edc].objectProperty" is what you need on the dynamically created model properties so that they all bind on post back.
Good luck. =)

How to add custom validation message using Asp.NET 4.5 and Razor view (Not MVC)

I have an ASP.NET 4.5 Web Site project which is using Razor views. This is not an MVC project, it is an empty web site with just a few .cshtml files in it.
I have a form where I want to validate. I found a site here that explains how to do this with a Razor view, but the Validation class does not have the methods shown in the example. I then came across the required attribute in HTML5, and I added that to each <input> in my form. This is validating the form when I submit it, but it is using generic error messages like shown in the image:
Here are my questions:
Is there some way to customize these messages?
Is there some way to validate other requirements besides required - like making sure its a number, or a certain length, etc?
*Note** I am not using MVC, so no models, etc. I also was trying to use something built in to ASP.NET if possible, and not use jQuery Validation directly.
Thanks in advance!
You can set your custom message with data-val-required attribute.
Make sure you added the jquery validation and Microsoft jquery unobstrustive js file in your page.
Below are the example. You can mix all data-val attributes and achieve all your combination
Example 1: Required, length
<input type="text" value="" name="UserName" id="checking-user"
data-val="true"
data-val-required="The UserName field is required."
data-val-length-max="100"
data-val-length="The field UserName must be a string a maximum length of 100."
/>
Example 2: Required, Number and Regex
<input type="text" value="" name="PaidAmount"
data-val="true"
data-val-required="Amount is required"
data-val-regex-pattern="[-+]?[0-9]*\.?[0-9]?[0-9]"
data-val-regex="Amount should be in numbers"
data-val-number="The field PaidAmount must be a number."
/>
Yeah you can do a lot of validation with HTML5 only
Along with the text input type, there are now a host of other options,
including email, url, number, tel, date and many others.
You can use setCustomValidity to customize messages and whatnot.

ASP.NET MVC: Hidden field value does not get rendered using HtmlHelper.Hidden

Something pretty weird is happening with my app:
I have the following property in my ViewModel:
public int? StakeholderId { get; set; }
It gets rendered in a partial view as follows:
<%= Html.Hidden("StakeholderId", Model.StakeholderId) %>
The form is submitted, and the relevant controller action generates an id and updates the model, before returning the same view with the updated model
The problem I'm experiencing is that the hidden field does not have anything in its "value" attribute rendered the second time even though StakeholderId now has a value.
If I just output the value on its own, it shows up on the page, so I've got it to render the value by doing this:
<input type="hidden" id="StakeholderId" name="stakeholderId" value="<%: Model.StakeholderId %>" />
But it's pretty strange that the helper doesn't pick up the updated value?
(I'm using jQuery to submit forms and render the action results into divs, but I've checked and the html I get back is already wrong before jQuery does anything with it, so I don't think that has much to do with anything)
UPDATE
I've since discovered that I can also clear the relevant ModelState key before my controller action returns the partial view.
The helper will first look for POSTed values and use them. As you are posting the form it will pick up the old value of the ID. Your workaround is correct.
ADDENDUM: Multiple HTML Forms, eg, in a Grid
As an addendeum to this issue, one thing to be VERY careful of is with multiple forms on the same page, eg, in a grid, say one generated using Ajax.BeginForm.
You might be tempted to write something along the lines of:
#foreach (var username in Model.TutorUserNames)
{
<tr>
<td>
#Html.ActionLink(username, MVC.Admin.TutorEditor.Details(username))
</td>
<td>
#using (Ajax.BeginForm("DeleteTutor", "Members",
new AjaxOptions
{
UpdateTargetId = "AdminBlock",
OnBegin = "isValidPleaseWait",
LoadingElementId = "PleaseWait"
},
new { name = "DeleteTutorForm", id = "DeleteTutorForm" }))
{
<input type="submit" value="Delete" />
#Html.Hidden("TutorName", username)
}
</td>
</tr>
}
The lethal line in here is:
#Html.Hidden("TutorName", username)
... and intend to use TutorName as your action's parameter. EG:
public virtual ActionResult DeleteTutor(string TutorName){...}
If you do this, the nasty surprise you are in for is that Html.Hidden("TutorName", username) will, as Darin Dimitrov explains, render the last POSTed value. Ie, regardless of your loop, ALL the items will be rendered with the TutorName of the last deleted Tutor!
The word around, in Razor syntax is to replace the #Html.Hidden call with an explicit input tag:
<input type="hidden" id="TutorName" name="TutorName" value='#username' />
This works as expected.
Ie:
NEVER, EVER USE Html.Hidden TO PASS A PARAMETER BACK TO YOUR ACTIONS WHEN YOU ARE USING MULTIPLE FORMS IN A GRID!!!
Final Caveat:
When constructing your hidden input tag, you need to include both name and id, set to the same value, otherwise, at the time of writing (Feb 2011) it won't work properly. Certainly not in Google Chrome. All you get is a null parameter returned if you only have an id and no name attribute.

Categories