Loading a partial view dynamically and loading index from controller - c#

I am at a loss on how to do this. I've tried every search I can think of. Any help/direction would be greatly appreciated.
The customer wanted to be able to load a partial view dynamically from a wysiwyg editor. So, I made a method in the controller that searches for a special tag that gets the name of the partial view. Got that to work fine. Now the customer wants to load and post data to/from the partial view.
I was able to get it loaded by doing this - finalhtml += PartialView("~/Views/Global/Partials/" + commandContents + ".cshtml").RenderPartialViewToString();
If I name the controller the exact name of the partial view plus controller ie: SamplePartialController, I can get the view post back to the controller, BUT I can't figure out how to load an initial index method on the partial no matter what I try.
It would be nice if I could define the initial index method and controller name programmatically, just not seeing a way.
I am fairly new to mvc, been doing asp.net for over a decade, and this may be very obvious, but I'm just not finding a way. Thanks!

Not sure I understand clearly the issue. I also had a lot of troubles working with partial views (to post data, to load them back if something wrong happened in the post action...).
It seems like you want to fill your partial view if some parameters are here when loading the index.
In the Controller.Index (or where you get your parameters) you can assign some ViewModel values, or use the ViewBag/ViewData.
In the index view, you can call where you need the RenderPartialAsync() based on your parameters setted previously
this.ViewData["error"] = Model.Error;
this.ViewData["partialGuid"] = Guid.NewGuid();
this.ViewData["foo"] = bar;
await Html.RenderPartialAsync("_PartialViewName", Model.PartialViewModel, this.ViewData);
And use your partial view the same way you do from an ajax call.
If you need to post data from your partial view, I struggled a lot with some things:
A FormContext is required in the partial view
#if (this.ViewContext.FormContext == null)
{
this.ViewContext.FormContext = new FormContext();
}
If you allow to push multiple times your partial view and post them, making a custom collectionId helps a lot when in the controller post action
#{
var collectionId = $"PartialItems[{this.ViewData["partialGuid"]}].{{0}}";
}
// then later...
<input class="form-control"
data-val="true"
data-val-required="#(string.Format(ApplicationResources.Error_Required, ApplicationResources.FieldFirstName))"
id="#(string.Format(collectionId, "FirstName"))"
name="#(string.Format(collectionId, "FirstName"))"
type="text"
value="#(string.IsNullOrWhiteSpace(Model.FirstName) ? string.Empty : Model.FirstName)" />
<span class="field-validation-valid text-danger"
data-valmsg-for="#(string.Format(collectionId, "FirstName"))"
data-valmsg-replace="true"></span>
// And in your Index ViewModel, something like that to get the collection in the controller post action
public IDictionary<string, PartialViewModel> PartialItems { get; set; }
If you call the new partial view with Ajax, after the first render of the view, reset the jquery validator if needed
$.ajax({
// ...
success: function (res) {
// do your stuff
$('#parentId').prepend(res);
// reinit the validation
$("form").each(function () { $.data($(this)[0], 'validator', false); });
$.validator.unobtrusive.parse("form");
}
});
It is almost everything I can think of that bugged me when dealing the first time with all this partial view things. Hope something here can help you.

Related

Issue with Updating Model in Razor View

first post. Trying so solve an issue I am seeing here between my Razor view and model. I have a popup window that is being fed a partial view and model.
public IActionResult ClickedCovid19Question(int id)
{
var existingQ = db.CustomerInfoItems.Find(id);
var suffix = existingQ.Suffix;
if (suffix.Length == 2)
suffix = suffix.Insert(0, "0");
var salesman = SalesmanHelper.GetSalesmanNum();
var par = db.Pars.Where(p => p.AccountNo == existingQ.CustNum).Where(p => p.Suffix == suffix)
.Where(p => p.SalesmanNumber == salesman).FirstOrDefault();
var clickedCovid19Model = new ClickedCovidQuestionModel
{ //insert model data here }
clickedCovid19Model.Machines = db.MachinePopulationItems
.Where(m => m.CustNum == existingQ.CustNum)
.ToList();
return View("~/Views/Covid19/_ClickedCovid19Question.cshtml", clickedCovid19Model);
}
This works great on the first page render. I see the data fill my UI elements that are called from the #model on the razor page. When my user updates a field here and submits, I use this function
function SaveClickedCovid19Question(idJS) {
C19ParChanged('#Model.Par');
var jsonJS = SerializeForm("#c19QuestionForm");
$.ajax({
url: '/Covid19/SaveClickedCovid19Question',
type: 'GET',
data:
{
id: idJS,
json: jsonJS
},
success: function (data) {
Alert(data);
RefreshLV("CovidQuestions");
HideWindow("#Covid19Question");
},
error: function (data, error, e2) {
debugger;
}
});
}
However, after the popup window is closed, and another popup is opened, we call that same ClickedCovid19Question IActionResult to populate our form again. It populates the UI fine with the new model it generated, debugging shows it creates a new model with all the correct data.
The issue arrises when a user submits this form again, the model on the Razor view seems to think it is still the model of the very first submission. An example of this is the first line of the javascript function. When the razor view was created, it had the correct #Model.Par data, as I could see when I created a few elements to display it. However, when trying to capture that data using #Model.Par, it captures the original Model.Par data.
Long story short, subsequent popups don't overwrite the Model data from the very first one. I am stumped, because this system works in so many other areas of our codebase.
I can fix this buy creating hidden elements that will store the data I need to send in any requests, but I feel like there has to be a better answer than that.
Edit: Below is an example I was using to test. The view part below will always display the correct par data in the id=parID input box. However, on the second popup and everytime after, if I was to run the simple javascript function below to find the data held by model, it will ALWAYS update to the data from the first model the page ever rendered, which seems inconsistent with other areas of my code that do work normally.
function updateParID() {
$("#c19QuestionForm").find("#parID").val('#Model.Par');
}
<input id="parID" type="text" disabled="disabled" value="#Model.Par"/>
<partial name="Forms/_FormDropDown" model=#(new FormDropDownModel { Name = "Par", Values = Lists.ParStates(), Value = Model.CallsPerYear}) />
<button type="submit" onclick="RefreshWindow('#Model.ID')">Refresh</button>
<button type="submit" onclick="updateParID()">Update Par ID</button>
That #Model.Par (or whatever prop you have in #Model) renders before anything shows up in browser.
Razor page will render your view and then pass it to browser.
so if you want to fetch data using ajax you should manually put data received from ajax into you html controls.
Have a nice coding day :)
So, I actually ended up solving this. My issue was, trying to bind the data from the #Model.Par or any model data INSIDE a javascript function will ALWAYS bind using the initial model. Every subsequent call to this function will ALWAYS only use that very first model.
My solution that I overlooked was to actually send the data to the function from the model as a parameter first, and not try to bind it inside the javascript function.
Example: My edit has these lines
function updateParID() {
$("#c19QuestionForm").find("#parID").val('#Model.Par');
}
<button type="submit" onclick="updateParID()">Update Par ID</button>
When I change the order of how I capture that model to this:
function updateParID(parID) {
$("#c19QuestionForm").find("#parID").val(parID);
}
<button type="submit" onclick="updateParID('#Model.Par')">Update Par ID</button>
This now correctly captures the model data that is present. I am sure there is some reason javascript works this way, but it is unknown to me, if anyone can shed light on it. Forgive me if it is a simple answer, I am new to web programming. Thank you all for helping out!

Need to pass parameter to multiple Partial Views on single view page

I am trying very hard to rewrite this question better than my previous effort which received no responses. Even though I’m nearly done with this application, I am still a relative newbie at programming and it seems like one challenge just leads to another. I have looked at many posts related to the problem of passing a parameter to several Partial Views in a single view page. So let’s take this in order from the AlertPick.cshtml page where the user chooses one of three Alert_Identifier/SelectedAlertIndex parameters from the application database. I’m only showing the #model and Select Tag Form.
#model edxl_cap_v1_2.Models.ContentViewModels.EdxlCapMessageViewModel
#{
<h4>#Model.Alerts.Count Alerts</h4>
<form asp-controller="Alerts" asp-action="PickAlert" method="post">
<select class="cap_select" id="cap_select" style="width:100%;max-width:95%;"
asp-for="SelectedAlertIndex" asp-items="Model.Alert_Identifiers">
<option>Select one</option>
</select>
<br />
<input type="submit" name="PickAlert" value="Pick Alert to Assemble EDXL-Cap Message" />
</form>
}
This takes the user to thePickAlert.cshtml page, a table of five rows where the first four rows are the Data Categories of the application: Alert, Info, Area and Resource each with the Alert_Identifier repeated as a reminder in a text box followed by its own submit button named Check Alert, Check Info, Check Area, and Check Resource, respectively. These submit buttons take the user to a _DetailsAlert.cshtml, _DetailsInfo.cshtml, _DetailsArea.cshtml, and _DetailsResource.cshtml pages and they work correctly, with the data item names and values from the record that matches the Alert_Identifier. The fifth row repeats the Identifier and its button reads Add All, to assemble the whole set together for review and takes the user to the_Assemble.cshtml page below, where the individual data categories are correctly assembled with the data item names, but lack the correct data values that match the record that corresponds to the Alert_Identifier. I’m thinking that I need to add a third parameter for the SelectedAlertIndex or Alert_Identifier to each of the #Html.Partial(...) Views, but I haven’t found the correct form/syntax for that, and If someone could supply that or point me to an example similar enough to this, I would deeply appreciate it.
#model edxl_cap_v1_2.Models.ContentViewModels.EdxlCapMessageViewModel
<!DOCTYPE html>
<head>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="~/css/capv1_2_refimp.css" />
<title>Assembled EDXL-CAP Message</title>
</head>
<h4>Assemble EDXL-CAP Message</h4>
<!-- DetailsAlert -->
<div class="content-wrapper">
#Html.Partial("_DetailsAlert", Model.Alert)
</div>
<!-- End of DetailsAlert -->
<!-- DetailsInfo -->
<div class="content-wrapper">
#Html.Partial("_DetailsInfo", Model.Info)
</div>
<!-- End of DetailsInfo -->
<!-- DetailsArea -->
<div class="content-wrapper">
#Html.Partial("_DetailsArea", Model.Area)
</div>
<!-- End of DetailsArea -->
<!-- DetailsResource -->
<div class="content-wrapper">
#Html.Partial("_DetailsResource", Model.Resource)
</div>
<!-- End of DetailsResource -->
Responding to first comment below, I'm showing the InfosController.cs code for _DetailsInfo(int? id) the controller action for the Info Data Category. It is virtually identical for each of the data categories except that the line ... .SingleOrDefaultAsync(m => m.InfoIndex == id); becomes ....SingleOrDefaultAsync(m => m.AlertIndex == id); and the method itself becomes_DetailsAlert(int? id).
// GET: Infos/Details/5
public async Task<IActionResult> _DetailsInfo(int? id)
{
if (id == null)
{
return NotFound();
}
var info = await _context.Info
//.Include(e => e.Elements)
// .ThenInclude(d => d.DataCategory)
.AsNoTracking()
.SingleOrDefaultAsync(m => m.InfoIndex == id);
if (info == null)
{
return NotFound();
}
return View(info);
}
PickAlert method from AlertsController follows:
public IActionResult PickAlert(Alert obj, int? SelectedAlertIndex)
{
if (SelectedAlertIndex.HasValue)
{
ViewBag.Message = "Alert loaded successfully";
}
return View(_context.Alert.Where(x => x.AlertIndex == SelectedAlertIndex));
}
I am not sure if I got the requirement correctly, but I think you have to create another model for all 4 partial views, e.g. for Alert, create a new model
class AlertModel:EdxlCapMessageViewModel
{
int SelectedAlertIndex {get;set;}
}
And then your view would look like:
<!-- DetailsAlert -->
<div class="content-wrapper">
#Html.Partial("_DetailsAlert",new AlertModel { Alert = Model.Alert,
SelectedAlertIndex = <ID SOMEHOW>
});
</div>
In .net core when I need to pass around a lot of data across the views, I usually find it cleanest to use services and DI. First, you can create a class that could store a set of data:
class MyDataForViews {
// the following is an example. You can have any properties
public string Info { get; set; }
}
You now have to add this class as a service. To do so go to your startup class and add the following within the services function:
services.AddScoped<MyDataForViews>();
Scoped means that the framework will create a new object of MyDataForViews for each HTTP request. No matter how many places you "inject" an object of MyDataForViews, it would use the same object across the current HTTP request. You can also replace the function with AddSingleton if you want to use the same object throughout the web app. The following is how you inject an object into your controller:
public class MyController : Controller
{
MyDataForViews myData;
// in controllers injection is done using the constructor
public MyController(MyDataForViews MyData) => myData = MyData;
public IActionResult Index()
{
myData = .... // assign all required data here
View();
}
}
Once this is done, instead of passing models to each view, you can inject the data into views using the following:
#inject MyDataForViews MyData;
Once you use this line on the top of any view, you can use the MyData object and there is no need to pass models to each partial view.
Here's a bit more detailed answer, since you've said at softwareengineering.stackexchange.com site that you still need help with this.
Let's first make sure you understand the basics correctly.
When it comes to passing data to the view, each controller in ASP.NET MVC has a property named ViewData, which is essentially a dictionary of key-value pairs. The ViewData itself has a property called Model, and this is what you access in the page using the Razor syntax #Model. You can use this property to pass a model that is strongly-typed, to avoid using magic strings for the keys of ViewData.
Note: ViewBag is a dynamic wrapper around the ViewData, so it's essentially the same thing (ViewBag.SomeProperty is the same as ViewData['SomeProperty']); the use of ViewBag is discouraged, though.
In a controller action when you do something like return View(), ASP.NET uses the cshtml page as a template to create actual HTML, and return it as the response to the client (this is all server-side).
There are a few ways to pass data to the view which are equivalent, for example:
ViewData.Model = someObject;
return View();
is the same as:
return View(someObject); // the View method can accept a model object
When it comes to partial views, by default, they get passed a copy of the parent page ViewData (this includes the reference to the Model), so you don't have to do anything special to pass this data to a partial view (but you can pass data of your choice if you want to).
The select tag helper renders (generates HTML) for the select element with the options specified. This is then sent as HTML to the client. On the client side, when the user clicks the submit button, a POST request is sent to the server, which is ultimately handled by the method PickAlert method on the AlertsController. If everything is setup correctly, you should get the SelectedAlertIndex as the parameter. Note that this is happening back at the server side, and that you now need to again return a page as the response.
You can pick the corresponding Alert object from your _context. Use the FirstOrDefault method for this instead of Where, as you only need a single item (convert types for comparison if necessary - e.g., if you have a string, but you are comparing to an int, or something along those lines).
var selectedAlert = _context.Alert.FirstOrDefault(x => x.AlertIndex == SelectedAlertIndex);
Now, all you need to do is set this selectedAlert and any other data that you need as a property on your model object (or under some key in ViewData), and render the correct view.
Note that if you just return View(model) without specifying the name of the view, the system will look for a view with the same name as your action method (here, PickAlert.cshtml), so use return View("ViewName", model) to change that if necessary.
For example, based on the code you've posted in your question, you could do something like this:
[HttpPost]
public IActionResult PickAlert(int? SelectedAlertIndex)
{
var model = new EdxlCapMessageViewModel(/* ... params, if any */);
if (SelectedAlertIndex.HasValue)
{
ViewBag.Message = "Alert loaded successfully";
var selectedAlert = _context.Alert.FirstOrDefault(x => x.AlertIndex == SelectedAlertIndex);
// I added a property to your model to store the alert;
// if you already have one, just use that one instead.
model.SelectedAlert = selectedAlert;
}
return View("YourViewName", model);
}
The YourViewName should be the parent view that has the partial views in it (the "Assembled EDXL-CAP Message" view, I presume).
BTW, I know that the way the system is passing the parameters to the action methods in a controller may seem a bit like magic, but it's convention-based. In the example above, it works because the parameter is named SelectedAlertIndex, and the model object has a property with the same name (and because you've specified that property in the select tag helper using asp-for="SelectedAlertIndex"). You can also modify the method signature so that it receives the entire model object (assuming that the model class is not too complicated - you can read more about how parameter binding works here):
[HttpPost]
public IActionResult PickAlert(EdxlCapMessageViewModel model)
{
// extract the index from model.SelectedAlertIndex
// you can also pass this same model object to the view
// (set some properties first if necessary)
// ...
}
Now for the partial views. Assuming that you are relying on the default mechanism which passes the parent ViewData to each partial view, you need to modify each partial view so that the code is written under the assumption that you can access the selected alert using #Model.SelectedAlert (the property you've set in the PickAlert action).
For example, a here's a simple partial view:
<div style="border: solid 1px #000000; padding: 30px; margin: 2px 2px 10px 2px;">
<p>The selected index is: #Model.SelectedAlert.AlertIndex</p>
</div>
Note that I'm just using the same model as in the parent view to access the SelectedAlert object: #Model.SelectedAlert.AlertIndex.
Again, when rendering the partial views, if you pass no additional parameters, they'll get a copy of the ViewData dictionary, and the same Model:
#Html.Partial("_DetailsAlert");
If you pass something else as the model, e.g., only the selected alert, then you need to change the partial view code accordingly:
#Html.Partial("_DetailsAlert", Model.SelectedAlert);
<div style="border: solid 1px #000000; padding: 30px; margin: 2px 2px 10px 2px;">
<p>The selected index is: #Model.AlertIndex</p>
</div>
Note that now, in the partial view, the local #Model refers to what was #Model.SelectedAlert in the parent view. (In other words, here #Model is of type Alert.) This only affects the ViewData.Model property; the key-value pairs stored in ViewData are still the same as those in the parent view.

My PartialView is causing my application to breakdown everytime

I'm trying to load my partial view with some data from database, but I'm getting following issue when I run the application:
Child actions are not allowed to perform redirect actions.
I don't know why this is happening because I'm pretty new with MVC technology.
Here is my PartialViewResult method in a controller:
public PartialViewResult UnReadEmails()
{
if (User.Id != null)
{
List<Emails> resultList = EmailController.GetUnreadEmailsByUserId(User.Id);
return PartialView("~/Views/Emails/_UnReadEmails.cshtml", resultList);
}
return PartialView("Error, not found!");
}
And here is my partialview itself, it is called _UnReadEmails (as you can see I'm displaying here info about sender and email body), PartialView is retrieving list of Emails that I'm sending to from my Controller
#model IEnumerable<Emails>
foreach (var item in Model)
{
<li>
<a>
<span>
<span>#item.EmailSender</span>
<span class="email">
#item.Body;
</span>
</a>
</li>
}
After I tried to load my partial view on this way:
#Html.Action("UnreadEmails", "Message")
I started to receive following issue that I mentioned in my Title,
I already tried few things to solve this like changing #Html.Action("UnreadEmails", "Message") to #Url.Action("UnreadEmails", "Message") etc etc but that didn't solve my issue.
EDIT: It allways breaks on this line (on view) :
#Html.Action("UnreadEmails", "Message")
It never goes into code behind..
After Chris suggestion on another post I added [AllowAnonymous] on the top of the method:
[AllowAnonymous]
public PartialViewResult UnReadEmails()
{
if (User.Id != null)
{
List<Emails> resultList = EmailController.GetUnreadEmailsByUserId(User.Id);
return PartialView("~/Views/Emails/_UnReadEmails.cshtml", resultList);
}
return PartialView("Error, not found!");
}
EDIT EDIT EDIT:
Interesting fact is that whatever I wrote in my Controller's method and even if I comment all code, it will still break on a View, that means it will never came into a Controller's method. I put breakpoing there at the begining of the UnReadEmails method and it was never hitted, it allways breaks on a View!
EDIT AFTER MAURIZIO suggestion to change it to #Html.RenderPartial
Than I received following issue:
The partial view 'UnReadEmails' was not found or no view engine
supports the searched locations. The following locations were
searched: ~/Views/Dashboard/UnReadEmails.aspx
~/Views/Dashboard/UnReadEmails.ascx ~/Views/Shared/UnReadEmails.aspx
~/Views/Shared/UnReadEmails.ascx ~/Views/Dashboard/UnReadEmails.cshtml
~/Views/Dashboard/UnReadEmails.vbhtml
~/Views/Shared/UnReadEmails.cshtml ~/Views/Shared/UnReadEmails.vbhtml
EDIT:
Compiler Error Message: CS0120: An object reference is required for the non-static field, method, or property 'MessageController.UnReadEmails()'
I tried to make UnReadEmails() as static but than I received following error :
Error 1 An object reference is required for the non-static field,
method, or property 'System.Web.Mvc.Controller.PartialView(string,
object)' ...Controllers\Message\MessageController.cs
Since your partial view is not in the Shared folder you need to provide the full path
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml")}
Since that view needs the list of emails you need to add that as parameter
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",EmailController.GetUnreadEmailsByUserId(User.Id))}
The best aproach would be to create a property in the Model (List<Emails> lstUnreadEmails) and load that list of emails in a method of the MessageController, so that the information is ready for the partial to be render with this instruction:
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",Model.lstUnreadEmails)}
In case you dont have a "main model" you could store that in a ViewBag, calling this from a MessageController method
ViewBag.lstUnreadEmail‌s = E‌​mailController.Get‌‌​​Un‌​readEmailsByUserId(U‌​ser.Id);
And in the View use this
{#Html.RenderPartial("~/Views/Emails/_UnReadEmails.cshtml",ViewBag.lstUnreadEmail‌​s)}

ASP.Net WebForms User Controls With Code Behind In MVC

I'm trying to move from the Old WebForms .NET approach to the newer MVC version. I just can't seem to find a solution to this issue.
In my current projects I use a lot of custom made User Controls. These controls will in almost all cases have several properties that are populated as parameters in the code behind of the parent 'aspx' page.
The User Control will have an 'ascx' page where all the html and controls exist. There will also be a 'ascx.cs' file attached to it where all the properties, methods and back-end logic occur.
What I can't seem to work out is how this logical process works in MVC? The .ascx file is similar to an MVC PartialView... that does make sense.
But where do you store all the backend logic for a PartialView?
How do I set multiple properties and construct the View based on these values?
I've seen some people suggesting you can still use .ascx files in MVC but I'm not sure this is the correct route to go down... certainly not the best practice route anyway?
I'll give a small example which may help:
country.aspx
<%# Register tagprefix="CUSTOM" tagname="Weather" src="~/controls/Weather.ascx" %>
<CUSTOM:Weather ID="Weather" runat="server"></CUSTOM:Weather>
country.aspx.cs
Weather.W_CountryCode = CountryCode;
Weather.W_CountryName = CountryName;
weather.ascx.cs
public string W_CountryCode { get; set; }
public string W_CountryName { get; set; }
Ok that is very basic structure of a control.
The control is embedded into the parent page.
Parameters are set in the code behind of the parent page.
The properties in the control will be used to collect the selected countries weather data from the database as well as running various other methods.
This easily reusable self contained code... I just can't see how you do the same thing in MVC? Where do you set the parameters... where is the code behind for the View stored?
Thanks in advance for any help
When you create a "page" in MVC, you have a controller action that builds a model and passes it to a view.
A "partial" page works exactly the same way - you have a controller action that builds a model and passes it to a view.
The only difference is that the action returns View() or PartialView().
When you want to re-use the partial, you can do so in two ways - load via the action or load via the partial. When you load via the action #Html.Action, you call the controller-action (perhaps with parameters) and that action builds the model and returns the (partial) view. When you load via #Html.Partial your view passes the model to the partial directly (ie not via a controller). Either is acceptable, it depends on how you are building the partial and whether you've already loaded some data or not etc.
So, for your example:
StaffViewModel.cs (partial)
public string W_CountryCode { get; set; }
public string W_CountryName { get; set; }
Staff.cshml (partial)
#model StaffViewModel
<div>Country: #Model.W_CountryCode / #Model.W_CountryName</div>
CountryViewModel.cs (view)
public IList<StaffViewModel> StaffList { get; set;}
Country.cshtml (view)
#model CountryViewModel
#foreach (var staff in Model.StaffList)
{
#Html.Partial("Staff", staff)
}
Controller.cs
public ActionResult Country()
{
var model = new CountryViewModel();
model.StaffList = new List<StaffViewModel>();
// populate staff list from DB etc here
return View(model);
}

Mvc3 Wizard with separate controller actions

I'm putting together a wizard in mvc3/c#. I have a model setup roughly
public interface IStepView {}
public class Step1View : IStepView {}
public class Step2View : IStepView {}
I have a parent view which displays 1 of 2 partial views for these steps.
I would like the form submission for Step 2 to use a custom action on the same controller. Reading similar posts it seems what I need to do is add a custom route like so
RouteTable.Routes.MapRoute("Step2Route", "", new { controller = "Demo", action = "MyAction" });
which I wire together on the Main.cshtml
#using (Html.BeginForm())
{
#Html.BeginRouteForm("Step2Route", new { controller = "RolloverController", action = "Stuff" })
// and so on for each Step I want to use a custom action
}
Is this the way to do it?
If you didn't know the number of steps in the wizard, a custom route might make sense to allow for tracking of progress in the wizard.
i.e. Wizard/{WizardName}Step/{StepNumber}/
But since it looks like you do know the steps, your actions on the controller can correspond to them without custom routes:
i.e RegistrationWizard/EnterInfo, RegistrationWizard/Confirm, RegistrationWizard/Success
Create a get and post method for each action on the controller. Take the same model and pass it along using RedirectToAction or store it in session, so that you keep track of the changes that the user is making to the data before committing the data on the final step.

Categories