Client Side Validation for Hidden Input in ASP.NET MVC - asp.net-mvc

I'm still a bit novice to the ASP.NET MVC architecture. I have an Edit page for data, which includes a hidden input. After testing my page, the 'Save' button wasn't doing anything and after some research learned it was a client-side validation issue.
After commenting the following line in the page:
#*#Html.HiddenFor(model => model.ID)*#
(where ID is a GUID), the page validated and posted.
From what I recall, the scaffolding put this code into my view. I just need to know how to fix this so that the ID field gets sent back properly to the controller and wanted to know why it wasn't validating.
Here is my View's code:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<div class="object_basics">
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}

Have you tried to add the validation message for the ID ?
#Html.ValidationMessageFor(model => model.ID)

Client side validation for hidden fields not working, because jQuery validation ignore all hidden tags.
You must define HiddenRequiredValidator class to achieve your goal.
You can read a solution to solve this problem Here

In view, update from:
#using (Html.BeginForm())
To
#using (Html.BeginForm(new{ID = model.ID}))
Remove the hidden element [#Html.HiddenFor(model => model.ID)].
In your controller, update the action properties like below
public ActionResult YourActionName(string ID, string Title)
Hopefully, this answers your question.
Cheers,
Danny

Related

How do you create a MVC view for navigation properties (one to many, many to many)

I have two ASP.NET MVC EF entities sharing an association:
When I am editing or creating the User, I'd like to be able to attach one or more UserRoles. So, my User Create view looks like this:
#model MyModels.UserViewModel
#{ ViewBag.Title = "Create"; }
#using (Html.BeginForm())
{
<fieldset>
<legend>User</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Username)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Username)
#Html.ValidationMessageFor(model => model.Username)
</div>
<!-- how to create an editor to add/remove roles -->
<div class="editor-label">
#Html.LabelFor(model => model.UserRoles)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserRoles)
#Html.ValidationMessageFor(model => model.UserRoles)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Since Model.UserRoles is initially empty, I get nothing in this line #Html.EditorFor(model => model.UserRoles). I tried adding a drop-down where I can select existing roles using JavaScript (I guess retrieved as partial view?), but I don't know how to append a selected role to the fieldset so that it gets submitted.
How is this usually done in ASP.NET? I have been searching SO for a while but cannot find the appropriate solution.
To clarify, what I don't understand is how to add/append a new role to the client side, so that the submit button actually sends this inside the UserRoles list.
(edit) Ok, I've found this: How to add an item to a list in a ViewModel using Razor and .NET Core. It says that I should fetch a partial view which is written to look like the inputs which would be generated by #Html.EditorFor (with the next array index), and then append it using JavaScript.
That looks quite weird, is that really the correct approach?

Incorrect Razor syntax

I'm having some trouble understanding how #Razor works in a view. The code below is my view where a user can create a new post (I'm creating a forum)
What I want to do is remove the <Fieldset>
My problem is that I can't change the code I've marked.
#model Forum3.Models.Posts
<h2>CreatePost</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
//--- CAN'T EDITED ----
<fieldset>
<legend>Post</legend>
#*SET TopicID*#
#{
Html.HiddenFor(model => model.TopicId);
#Html.Hidden("TopicId",ViewData["currentTopicId"]);
}
//----END----
<div class="editor-label">
#Html.LabelFor(model => model.Text)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Text)
#Html.ValidationMessageFor(model => model.Text)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
If I remove the <Fieldset> and <Legend> I get this error on my HiddenFor code:
Parser Error Message: Unexpected "{" after "#" character. Once inside the body of a code block (#if {}, #{}, etc.) you do not need to use "#{" to switch to code.
If I then remove the #{...} to look like this:
#Html.HiddenFor(model => model.TopicId);
#Html.Hidden("TopicId",ViewData["currentTopicId"]);
I'll get an error when I click Create because the TopicId is not being set to my currentTopicId (This also happens if I leave the <fieldset> in)
I have no idea what going on here. Any ideas?
I'm not having any errors with that once you remove the surrounding block and use the # on both fields. However, one thing you do have that's probably messing up your post - you have both a Hidden and a HiddenFor for the same property. So if you look at the rendered markup, you'll see it there twice, so it gets posted twice (I'm not sure which one it assigns to the posted model).
The HiddenFor is all you need - just make sure your model contains the TopicId value, and you don't need it in ViewData at all, so you can get rid of that second one.

How can I programmatically trigger client side validation set up by a Razor view?

I have a little Ajax application where I use Razor views to initially generated HTML form segments that I later read and write from with knockout.js. Although I am doing no non-Ajax action requests, I use Razor to generate the HTML so I enjoy automatic generation of jQuery Validation attributes. E.g. in my single page, I render a hidden form like this:
<section id="person-detail">
#Html.Action("EditPartial", "Person")
</section>
The EditPartial action returns a partial view that looks a lot like this:
#using (Html.BeginForm())
{
<fieldset>
#Html.HiddenFor(model => model.Id, new { data_bind = "value: id" })
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.FirstName, new { data_bind = "value: firstName" })
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<p>
Update
Delete
</p>
</fieldset>
}
Because I'm never actually posting the form, and due to some unknowns, despite all properties on my Person model being marked with the Required attribute, I see no sign of client side validation. What must I do to trigger this validation when my save button is clicked?
suppose your form has a class 'main':
$('form').submit(function() {
var $form = $('form.main');
$form.valid();
});

ASP.NET MVC3 - displaying "updated" model values for summary display before form submission

I have a view named AddEditModule that is used, believe it or not, for Adding or Editing a module. The workflow is kind of a wizard using navigation buttons that hide/show div's.
I've got a ViewModel called AddEditModuleModel (say that 10 times fast). In steps 1 & 2 I'm displaying my fields using various EditorFor's. In step 3, I'd like to use DisplayFor's to display a Summary of the current values of my textboxes (what's been updated in the View, not what was passed in in the model).
In my Silverlight days, I'd simply have two-way binding between my 'Step1.FirstName' TextBox and a ViewModel property. In my Summary, I could simply display a TextBlock that was also bound to my ViewModel property, or I could use Element Binding to bind my TextBlock.Text proeprty to my Step1.FirstName.Text property.
I know I can't do that in MVC3, but I'm not sure how to solve this. I thought about just ajax posting the updated module and returning a new partial view called ModuleSummary, or something similar, but that seemed kinda hacky (and not entirely sure if that would mess up my file upload on the page).
Is there something I'm missing?
[Edit - sample code]
Scenario:
I'm editing a model which originally has a title of "My Module". Obviously on initial load, my DisplayFor model.title is going to be set to "My Module". Let's assume, on step 1, I change the title to "My New Module Title". What I'd like to know is if there's a way to "refresh" my model when I click the button to display Summary to display my new title.
#model CEAcademy.AddEditModuleModel
#using (Html.BeginForm("AddModule", "Module", FormMethod.Post, new { enctype = "multipart/form-data" })) {
#Html.ValidationSummary(false)
<fieldset>
<legend></legend>
<div id="step1">
<div class="editor-label">
#Html.LabelFor(model => model.title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.title)
#Html.ValidationMessageFor(model => model.title)
</div>
</div>
<div id="summary">
<div class="display-label">
#Html.LabelFor(model => model.title)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.title)
</div>
</div>
<input type="button" id="showSummary" value="Step 2: View Summary" />
</fieldset>
}
Someone just asked a similar question
Display form data before final submission (confirmation view)
I'll ask you the same thing I asked that person. Do you need to go to the server? Is there some extra validation you need to do before displaying the summary?
If not, then you can "easily" do this client side. Use javascript (jQuery or some other lib) to display the summary and at the end then POST the data.

Add a non field related error to an asp mvc form

I'm having some troubles with ASP MVC error handling.
On a form that a user tries to connect to a device. If the uses input an invalid device name, it's pretty straightforward to tell the user the name is invalid.
I'm implementing IEnumerable<RuleViolation> GetRulesViolations() on all my data classes. The RuleViolation class has two fields: PropertyName and ErrorMessage and if I get an error on submit I just call the GetRulesViolations method and set the errors on the ModelState:
catch {
foreach (var issue in device.GetRulesViolations()) {
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View();
}
and with some background asp mvc magic the error appears on the view in the ValidationMessage placeholder for the model.Name:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Connect" />
</p>
</fieldset>
}
Now the problem:
If the error i'm getting is something like "Could not connect to the device" that's not a problem related to the Name field. It's a message that should appear above the form because it's related to the whole form.
Is there a straightforward way to set this like ModelState.AddError("error message") without telling the key so it would apply to the whole form or should I create an Error hidden property on the Data classes and place a validation message for that property above the form?
Yes, empty field name, like this :
ModelState.AddModelError("", issue.ErrorMessage);

Resources