How do I conditionally render a form in Razor? - asp.net

When I use the following code, I get a friendly error message (as friendly as YSCD's get) telling me I shouldn't use '#', yet when I don't use it, my form declaration renders as literal Razor code, not as the intended HTML elements. What am I doing wrong?
#if (Model.Step == Trocrates.Web.Models.PasswordResetModel.PasswordResetSteps.StartRequest)
{
#using (Html.BeginForm()) { Html.ValidationSummary(true);
<fieldset style="border: 0px;">
<div class="editor-label">
#Html.LabelFor(model => model.UserName);
</div>
<div class="editor-field">
Html.EditorFor(model => model.UserName) Html.ValidationMessageFor(model => model.UserName)'
<input type="submit" value="Log In" />
#Html.ActionLink("Send", "BeginResetPassword", "Account")
</div>
</fieldset>
}
}
Sorry readers, it was originally that less visible open brace glyph on the same line as BeginForm that caused confusion. When I close that things fell back into place.

Did you try removing the # symbol on the using statement? Since you're already in code mode because of the if block the # symbol doesn't mean anything there. That's the only thing off hand that looks out of place to me.

Related

Wizards in Mvc 4

I need to create a wizard in MVC 4 and most of the part I have done, now what is bothering me is that my project requires that the values which I have inserted in the first step of the wizard should display like label in the next step. How to achieve that, can anyone help me with this?? It would be great if I'll get a fast response.
Thank you in advance!!
This is how I am writing the front end code of the application
<div class="wizard-step">
<h3>Step 3: Check Eligibility</h3>
<div class="editor-label" style="width: 25%">
#Html.LabelFor(model => model.AccountNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AccountNumber)
</div>
<div class="editor-label" style="width: 25%">
#Html.LabelFor(model => model.MeterId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MeterId)
</div>
<div class="editor-label" style="width: 25%">
#Html.LabelFor(model => model.Program)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Program)
</div>
<div class="editor-label" style="width: 25%">
#Html.LabelFor(model => model.PeakLoad)
</div>
<div class="editor-field MB12">
#Html.CheckBoxFor(model => model.PeakLoad)
</div>
<div class="editor-label" style="width: 25%">
#Html.LabelFor(model => model.WifiBroadband)
</div>
<div class="editor-field MB12">
#Html.CheckBoxFor(model => model.WifiBroadband)
</div>
</div>
And the controller code is also there
[HttpGet]
public ActionResult EnrollUser()
{
EnrollmentEntity model = new EnrollmentEntity();
BindAggregatorList(model);
BindCBLMethod(model);
BindDeviceManuList(model);
BindDeviceModelList(model);
BindDeviceTypeList(model);
BindProgramList(model);
return View(model);
}
[HttpPost]
public ActionResult EnrollUser(EnrollmentEntity model)
{
return View(model);
}
If you're trying to keep things atomic, you can save the data from each step in a session object and then save everything together once the user has completed the wizard. You could also POST the data from the current and previous steps to the next step of the wizard.
Another option would be to save the partial to your database following each step of the wizard.
Update
Given the new constraints, and assuming you support only modern browsers (IE8+ and just about all versions of Firefox and Chrome that are in use), you could store the data using local storage. See Using the Web Storage API.
First of all thank you guys for showing your interest in my problem and trying to resolve it. It is the other thing that any of the answer didn't helped me out or might be the question was not explained properly. But now I got the answer and I am posting it so that it may help to other.
My problem was that I had to show the values that I have inserted in the first screen as Non editable in the second screen and for that I have just used the #Model.Username at the place I wanted to display it. And yes for the server side validation like the I have posted back the data after each screen and returned the same model.

Form validation for saving before exit

I created a form in asp.net and now I need to add a validation to it, so if any of the fields has been populated and user will try to leave the page, the pop-up will appear asking "Do you want to exit without saving?". Is there a simple way I can to this?
<% using (Html.BeginForm("Create", "Damages", FormMethod.Post))
{%>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%=Html.LabelFor(model => model.OrderId)%>
</div>
<div class="editor-field">
<%= Model.OrderId%>
</div>
....
<%=Html.HiddenFor(model => model.Id)%>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
You can use the onbeforeunload event:
<script>
window.onbeforeunload = function() {
if( isDirty ) {
return 'Do you want to exit without saving?';
}
}
</script>
Of course you need to keep track of form field changes and set the isDirty flag accordingly.
https://developer.mozilla.org/en-US/docs/Web/API/Window.onbeforeunload
http://msdn.microsoft.com/en-us/library/ie/ms536907%28v=vs.85%29.aspx

ASP.Net MVC 4 & Unobtrusive Validation Summary

I am trying to display a summary error message on a form as well as property level errors.
The property errors get rendered using html.validationmessagefor(model =>...) which works fine.
But when there is one or more validation errors, I want html.ValidationSummary(true) to display the message "Your form is missing some details - see below".
There also might be some server side validation which will occur post submit and will be added with ModelState.AddError.
How can I get a class level dataattribute (presumably using [AttributeUsage(AttributeTargets.Class)]) to display in the summary validation using unobtrusive validation?
Is this what you are looking for:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
#Html.ValidationSummary("Errors:")
<div>
#Html.EditorFor(model => model.PathToExcel)
#Html.ValidationMessageFor(model => model.PathToExcel)
</div>
<div>
<input type="submit" value="Load" />
</div>
}
this uses 2 ValidationSummary's, one to fill the ValidationMessageFor-fields and one to use a Summary. Summary only works after Submitting.

Create Views for object properties in model in MVC 3 application?

I have an Asp.Net MVC 3 application with a database "Consultants", accessed by EF. Now, the Consultant table in the db has a one-to-many relationship to several other tables for CV type information (work experience, etc). So a user should be able to fill in their name etc once, but should be able to add a number of "work experiences", and so on.
But these foreign key tables are complex objects in the model, and when creating the Create View I only get the simple properties as editor fields. How do I go about designing the View or Views so that the complex objects can be filled in as well? I picture a View in my mind where the simple properties are simple fields, and then some sort of control where you can click "add work experience", and as many as needed would be added. But how would I do that and still utilize the model binding? In fact, I don't know how to go about it at all. (BTW, Program and Language stand for things like software experience in general, and natural language competence, not programming languages, in case you're wondering about the relationships there).
Any ideas greatly appreciated!
Here's the Create View created by the add View command by default:
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Consultant</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<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>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
And here's the EF database diagram:
Update:
According to suggestion, I tried Steven Sanderson's blog solution, but I can't get it to work properly. I added this in the main view:
<div id="editorRows">
#foreach (var item in Model.Programs)
{
Html.RenderPartial("ProgramEditorRow", item);
}
</div>
<input type="button" value="Add program" id="addItem" />
I also added the javascript:
<script type="text/javascript">
var url = '#Url.Action("BlankEditorRow", "Consultant")';
$(document).ready(function () {
$("#addItem").click(function () {
$.ajax({
url: url,
cache: false,
success: function (html) {
alert(html);
$("#editorRows").append(html); }
});
return false;
});
});
</script>
A partial view:
#model Consultants.Models.Program
#using Consultants.Helpers
<div class="editorRow">
#*#using (Html.BeginCollectionItem("programs"))
{*#
#Html.TextBoxFor(model => model.Name)
#*}*#
</div>
And action methods in the controller:
public ActionResult Create()
{
Consultant consultant = new Consultant();
return View(consultant);
}
public ActionResult BlankEditorRow()
{
return PartialView("ProgramEditorRow", new Program());
}
Note that I commented out the Html.BeginCollectionItem part in the partial view, because I can't get that to work. It only gives me the hidden field Steven Sanderson talks about, but not the actual textbox. So I tried commenting that part out and just had a textbox. Well, that gets me the textbox, but I can't get to that info in the post method. I use the Consultant object as return parameter, but the Programs property contains no Program. Perhaps this has to do with the fact that I cannot get the BeginCollectionItem helper to work, but in any case I don't understand how to do that, or how to get to the Program supposedly added in the view. With a simple object I would add the new object in the post method by something like _repository.AddToConsultants(consultant), and when I save to EF it gets its id. But how do I do the same thing with the program object and save it to the database via EF?
Phil Haack has written a great blog post which explains how to model bind to a list. It's specific to MVC2, but I'm not sure if version 3 has improved on this.
Model Binding To A List.
In a scenario where the user is allowed to add an arbitrary number of items, you'll probably want to create new input fields using JavaScript. Steven Sanderson shows here how to achieve that:
Editing a variable length list, ASP.NET MVC 2-style.
Those resources should get you all the way there.
You may take a look at the following blog post about writing custom object templates. Also don't use EF models in your views. Design view models that are classes specifically tailored to the needs of a given view and have your controller map between the EF models and the view models that should be passed to the view. AutoMapper is a good tool that could simplify this mapping.

MVC2 Custom Editor Template outer validation box

I've got a custom Editor Template that is essentially:
<div id="control">
<%: Html.DropDownListFor(model => model.Day, Model.Days)%>
<%: Html.DropDownListFor(model => model.Month, Model.Months)%>
<%: Html.DropDownListFor(model => model.Year, Model.Years)%>
</div>
Whilst my validation is successful/fine with this control (ValidationMessageFor works) I have been unable to find how to highlight the control when validation fails (e.g. with a TextBoxFor the textbox border goes red if validation fails)
Does anyone know how I can add this behaviour with a custom editor template please?
Interesting question. If you can detect a validation error, then you should be able to apply the appropriate class. Something like this, substitute in your own field name:
<div id = "control" class="<%=ViewData.ModelState.IsValidField("DateField") ? "" : "validation-error" %>">

Resources