Wizards in Mvc 4 - asp.net

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.

Related

How to handle System.NullReferenceException? [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
#model MvcDemo.Models.MovieDB
<fieldset>
<legend>MovieDB</legend>
<div class="display-label">Title</div>
<div class="display-field">
#Html.DisplayFor(model => model.Title)
</div>
<div class="display-label">Director</div>
<div class="display-field">
#Html.DisplayFor(model => model.Director)
</div>
<div class="display-label">Date</div>
<div class="display-field">
#Html.DisplayFor(model => model.Date)
</div>
</fieldset>
<p>
#Html.ActionLink("Edit", "Edit", new { id=Model.ID })
#Html.ActionLink("Back to List", "Index")
</p>
When I am executing this , an error message is coming which is as follows ...
System.NullReferenceException: Object reference not set to an instance of an object.
The error is occuring at the 2nd last line i.e.#Html.ActionLink("Edit", "Edit", new { id=Model.ID })
In your action method, just before you return the ActionResult have a look at the model and confirm that the ID property is populated - I think you'll find it isn't.
If your action method is a HTTP Post, does the view that has been submitted contain a control for the ID field? If not, try using a "Hidden" input field - the HiddenFor(...) method will help you out with it...

ASP.NET Razor ViewModel property is modified somewhere

I have an extremely simple Controller + View
public ActionResult Edit(string username)
{
return View(ComponentFactory.GetAdapter<IUserListAdapter>().Get(username));
}
and
#model BAP.Models.UserList
#using GrmanIT.Utils.Web
#using BAP.Models
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Globale Benutzer</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserId)
#Html.ValidationMessageFor(model => model.UserId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Model.UserName
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Bundesland)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Bundesland, new SelectList((IEnumerable<BAP.Models.Bundesland>)ViewData["BundeslandList"], "Value", "Text"))
</div>
<div>
<input type="submit" value="#LocalizationHelper.LocalizedLiteral("Save").ToString()" />
</div>
</fieldset>
}
<div>
#Html.ActionLink(LocalizationHelper.LocalizedLiteral("BackToList").ToString(), "Index")
</div>
#Model.UserName
this is by far the simplest controller and view we have in our MVC4 application, BUT - it does something weird:
I get the TextBox, which is created with #Html.EditorFor(model => model.UserName) prefilled with the UserId of the model instead of the UserName
I debugged it and it and there as always the correct value in UserName and UserId. You can also see, that I added #Model.UserName twice within the View to see if it get also correctly rendered, and yes, it prints the UserName and not the ID.
I've also checked references to the UserName-property and didn't find any, which would modify it. My question is - do you have any idea, where the code could be modified or how could if find it out?
It happens only on this one controller on this one action (out of ~25 controllers and ~200 actions)
Thank you
Ok, it was AGAIN the ModelState - as you can see in the code above - the parameter to the function is called "username" but it's actually the userId. And since there is already the parameter username, it is stored in the ModelState and when I call
#Html.EditorFor(model => model.UserName)
it takes the value from the ModelState (where actually the UserId is stored under the name of the action-parameter)
So the solution would be, either to call ModelState.Clear() or rather, rename the parameter to represent the actual value.

MVC3 - Razor Edit/Create scaffold templates use DisplayName annotation. Delete/Details does not. Why?

Using MVC3 for the first time, so sorry for the noob-like question.
I'm trying to annotate my data model for the UI layer. In my model, I have the following
[DisplayName("First Name")]
public string firstName { get; set; }
When I create a view based on the Details/Delete scaffold, it generates the following:
<div class="display-label">firstName</div>
<div class="display-field">
#Html.DisplayFor(model => model.firstName)
</div>
This does not, obviously, use my annotated model. When I create a view based on the Create/Edit scaffold, it generates this HTML:
<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>
Because it's using the #Html.LabelFor, it ultimately uses my annotated model as I anticipated.
Obviously I can see the common thread - the first two are editable, the second two are readonly. I cannot imagine why they would save me the trouble on two of them, and not on the others, but I'm sure there has to be a reason, right?
So if there IS a reason, is my only solution to manually go through each of the views & change the content from firstName to First Name?
I don't know why they did that either, but you can create your own display template for objects as explained here that uses your annotation.

How do I conditionally render a form in Razor?

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.

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.

Resources