Displaying a string array in Razor Pages? - visual-studio

I'm trying to print out a string as a list in a Razor Page. I have the following:
Aboud.cshtml.cs:
public void OnGet()
{
Message = "Hello";
Message = AddToMessage(new string[] {
"This is my first page",
"By the end of this course",
"I will be a Razor Pages Pro!"});
}
private string AddToMessage(string[] text)
{
string result = "";
foreach (string txt in text)
{
result += txt + "\n";
}
result = ReplaceToUpper(result);
return result;
}
private string ReplaceToUpper(string text)
{
return text.ToUpper();
}
About.cshtml:
#page
#model AboutModel
#{
}
<h1>This is the about page!</h1>
<br />
<p>#{
string[] message = #Model.Message.Split("/n");
foreach(string text in message)
{
<br /><p>#text</p>;
}
}
</p>
The page keeps printing out the line in one string. I've also tried using an unordered/ordered list as the HTML markup and I'm not able to make it work.

Need other backslash so \n instead of /n
#page
#model AboutModel
#{
}
<h1>This is the about page!</h1>
<br />
<p>#{
string[] message = #Model.Message.Split("\n");
foreach(string text in message)
{
<br /><p>#text</p>;
}
}
</p>

Related

I need to send a string to the controller then send result back to View in MVC.net

I am trying to make an web app with MVC.Net to display text boxes in the view where a vmware hostname is entered then the value is taken from the box from a button click and sent to the controller which then searches for it using an external SQL server with the resulting vcenter sent back to the text box. Right now I have the SQL working with a statically entered host name (test1) , so I click on the button and it does return the vcenter from sql, but I need to know how to be able to have the value sent back from the text box from the view to the controller, then the result sent back to the view, please help. I find this MVC ridiculously convoluted and difficult especially compared to asp.net webforms.
I have the following code for the view
#{
#model getdata
<script type="text/javascript">
function Hello() {
var yourJavaScriptArray = #Html.Raw(Json.Serialize(Model.Name));
ResourcePool.value = "Hello!";
ipnumber.value = yourJavaScriptArray;
}
</script>
<tr>
<td><b>vCenter Name: </b></td>
<td> #Html.TextBox("vCenter", " ", new { style = "color:blue" })</td>
<td><input type="submit" value="TestQuery" button style=" width:140px;" onclick="Hello()" /></td>
</tr>
Then the model is simple -
namespace WebApplication1.Models
{
public class getdata
{
public string Name { get; set; }
public string read1 { get; set; }
public string textfrombox { get; set; }
public string searchText1 { get; set; }
}
}
Then for the controller -
[HttpPost]
public ActionResult Search(string searchText)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["sqlconnection"].ConnectionString);
var model = new Models.getdata();
string test1 = " HostName " ;
string textToQuery = "%" + test1.Trim() + "%";
string hosttest = ("select vcenter from db_owner.host where name like #textToQuery");
SqlCommand cmdhosts = new SqlCommand(hosttest, conn);
conn.Open();
cmdhosts.Parameters.AddWithValue("#textToQuery", textToQuery);
using (SqlDataReader read = cmdhosts.ExecuteReader())
{
while (read.Read())
{
// model.read1 = (read["Name"].ToString().Trim());
model.read1 = (read["Name"].ToString().Trim());
}
}
conn.Close();
model.Name = model.read1;
model.searchText1 = model.read1;
return View(model);
// return View(name);
}

ASP.Net Core 3.1 and global view method

The code #await Html.PartialAsync("~/Views/Shared/_Toast.cshtml", new ToastMessage() { Caption = "Hello", Message = "World" }) renders a partial view with arguments. It shows a Bootstrap toast message, which I intend to use everywhere.
Now is it possible to reduce that line to something like #MyHelpers.ShowToastMessage(new ToastMessage() { Caption = "Hello", Message = "World" })? I don't want to use View Components (overkill). Also #functions block seems to be local only.
You can custom a htmlhelper in your app.
namespace App.Helpers
{
public static class HtmlHelperExtensions
{
public static IHtmlContent ShowToastMessage(this IHtmlHelper htmlHelper, ToastMessage model)
{
string str = "<div> "+ model.Caption + " " + model.Message + " <div/>";
return new HtmlString(str);
}
}
}
In your view:
#using App.Helpers
#await Html.PartialAsync("~/Views/Shared/_Toast.cshtml", new ToastMessage() { Caption = "Hello", Message = "World" })
#Html.ShowToastMessage(new ToastMessage() { Caption = "Hello", Message = "World" })
If your _Toast.cshtml contains other html elements, then you can use TagBuilder Class to create.

APEX - Why aren't my input validations working?

I'm working on a contact search page and I have a problem. My console has no errors but when I run a search, the results don't generate and all of my input validation errors prompt.
For Example:
Jane Grey
The Search for Jane Grey
Here is my VisualForce page:
<apex:page id="ContactPage" controller="Ctrl_ContactSearch">
<apex:tabPanel id="ContactPanel">
<apex:tab id="ContactTab" label="Contact Search">
<apex:form id="ContactForm">
<!-- Input Fields -->
<apex:pageBlock title="Contact Search Page" id="ContactBlock">
<apex:pageBlockSection id="contact-table" columns="3">
<apex:pageBlockSectionItem id="NameInputBlock">
<apex:outputLabel value="Name" />
<apex:inputText id="NameInputField" value="{!name}" />
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem id="PhoneInputBlock">
<apex:outputLabel value="Phone" />
<apex:inputText id="PhoneInputField" value="{!phone}" />
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem id="EmailInputBlock">
<apex:outputLabel value="Email" />
<apex:inputText id="EmailInputField" value="{!email}" />
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<!-- Buttons -->
<apex:pageBlockButtons location="bottom">
<apex:commandButton value="Search Contacts" action="{!searchContacts}" />
<apex:commandButton value="Clear Fields" action="{!ClearFields}" />
</apex:pageBlockButtons>
</apex:pageBlock>
<!-- Results Display -->
<apex:pageBlock title="Results" rendered="{!contacts.size!=0}" >
<apex:pageBlockSection >
<apex:pageBlockTable value="{!contacts}" var="c" id="contact-table">
<apex:column >
<apex:facet name="header">Name</apex:facet>
{!c.Name}
</apex:column>
<apex:column >
<apex:facet name="header">Phone Number</apex:facet>
{!c.Phone}
</apex:column>
<apex:column >
<apex:facet name="header">Email</apex:facet>
{!c.Email}
</apex:column>
</apex:pageBlockTable>
</apex:pageBlockSection>
</apex:pageBlock>
<!-- Error Display -->
<apex:pageBlock title="Errors" id="ErrorSection" >
<apex:pageMessages id="ErrorsListing">
</apex:pageMessages>
</apex:pageBlock>
</apex:form>
</apex:tab>
</apex:tabPanel>
<script type = "text/javascript">
var name = document.getElementByID("name");
var phone = document.getElementByID("phone");
var email = document.getElementByID("email");
</script>
</apex:page>
Here is my Controller:
public with sharing class Ctrl_ContactSearch
{
public List<Contact> contacts { get; set; }
public String name { get; set; }
public String phone { get; set; }
public String email { get; set; }
public integer MatchingContacts { get; set; }
public boolean ErrorsPresent = false;
public boolean Error_NoResults = false;
public boolean Error_FieldsEmpty = false;
public boolean Error_NameSyntax = false;
public boolean Error_PhoneSyntax = false;
public boolean Error_EmailSyntax = false;
/* Name Input Validation Regex*/
public static Boolean ValidationName (String name)
{
Boolean NameIsValid = false;
String nameRegex = '/^[a-zA-Z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*(__[cC])?$/';
Pattern PatternName = Pattern.compile(nameRegex);
Matcher nameMatcher = PatternName.matcher(name);
if (nameMatcher.matches())
{
NameIsValid = true;
}
return NameIsValid;
}
/* Phone Input Validation Regex*/
public static Boolean ValidationPhone (String phone)
{
Boolean PhoneIsValid = false;
String phoneRegex = '//^\\(?([0-9]{3})\\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$//';
Pattern PatternPhone = Pattern.compile(phoneRegex);
Matcher phoneMatcher = PatternPhone.matcher(phone);
if (phoneMatcher.matches())
{
PhoneIsValid = true;
}
return PhoneIsValid;
}
/* Email Input Validation Regex*/
public static Boolean ValidationEmail (String email)
{
Boolean EmailIsValid = false;
String emailRegex = '/^\\w+([\\.-]?\\w+)*#\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$//';
Pattern PatternEmail = Pattern.compile(emailRegex);
Matcher emailMatcher = PatternEmail.matcher(email);
if (emailMatcher.matches())
{
EmailIsValid = true;
}
return EmailIsValid;
}
/* Runs when "Clear Fields" button is pressed*/
public void ClearFields()
{
name = '';
phone = '';
email = '';
}
/* Runs when "Search Contacts" button is pressed*/
public PageReference searchContacts()
{
/* Checks if input fields are empty*/
if (name == '' && phone == '' && email == '')
{
Error_FieldsEmpty = true;
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Your fields are blank. Please enter your information in the remaining fields to proceed'));
}
else
{
/* Checks Input Validation Results*/
if (ValidationName(name) == false)
{
Error_NameSyntax = true;
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Inproper name format. Please enter name in following format : Firstname Lastname.'));
}
if (ValidationPhone(phone) == false)
{
Error_PhoneSyntax = true;
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Inproper phone number format. Please enter number in following format : XXX-XXX-XXXX.'));
}
if (ValidationPhone(email) == false)
{
Error_EmailSyntax = true;
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Inproper email format. Please enter email in following format : XXX#emailprovider.com'));
}
/* Runs if all Validation results are 'true'*/
if (ValidationName(name) == true && ValidationPhone(phone) == true && ValidationPhone(email) == true)
{
contacts = [select Name, Phone, Email from Contact where Name = :name or Phone = :phone or email = :email];
MatchingContacts = contacts.size();
/* Checks if/how many matches were found from the search*/
if(MatchingContacts != 0)
{
system.debug('There are currently ' + MatchingContacts + 'results found.' );
}
else
{
Error_NoResults = false;
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'No matching Contacts were found.'));
}
}
}
/* Displays "Error" field if any errors are found*/
if (Error_NoResults == true || Error_FieldsEmpty == true || Error_NameSyntax == true || Error_PhoneSyntax == true || Error_EmailSyntax == true)
{
ErrorsPresent = true;
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.WARNING,'There are errors present. Please read and follow instructions accordingly.'));
}
return null;
}
}
What do I have wrong here?
For some reason StackOverflow won't let me make this post without adding extra text. I'm putting this here to increase the wordcount.
1st, some constructive criticism:
The DRY principle says you should combine your validation methods into 1.
2nd, it looks like your regexs weren't good. Depending on the exact requirements of the validation, you can try these below... Taken willy nilly from other replies to other questions on forums much like this one... (I am by no means a Regex expert)
Try something like this:
private string nameRegEx = '^[a-zA-Z][a-zA-Z0-9 ]+$';
private string emailRegEx = '^[a-zA-Z0-9._|\\\\%#~`=?&/$^*!}{+-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$';
private string phoneRegEx = '^(\\d{3}\\-\\d{3}-\\d{4})?$';
public static Boolean Validate (String str, String validation)
{
Boolean IsValid = false;
Pattern Pattern = Pattern.compile(validation);
Matcher Matcher = Pattern.matcher(str);
if (Matcher.matches())
{
IsValid = true;
}
return IsValid;
}
Also, this function returns a Boolean. When checking its return value, you don't need the equality operators. Just use if (Validate(name, nameRegex)) { ... } or if (!Validate(email, emailRegex)) { ... }

ASP NET MVC 5 i18n using Nadeem's code, but I want to add returnUrl

I am going to include the code how I have it. I felt like what I had should work because I got no squiggly lines. lol But I end up with a Redirect Loop.
First off I got the basic implementation from Nadeem Afana's blog. I don't think the CultureHelper.cs or the BaseController.cs may be needed to implement a returnUrl functionality, but since they are part of the code I am including them here so that you don't have to dig through his website to look for it. I have tried to eliminate scrolling for you as well.
HERE IS MY CODE:
Helpers/CultureHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
namespace xxxUSA.Helpers
{
public static class CultureHelper
{
// Valid cultures REMOVED SOME CODES FOR BREVITY
private static readonly List<string> _validCultures = new List<string>
{ "en-AU", "en-BZ", "en-CA", "en-029", "en-IN", "en-IE", "en-JM",
"en-MY", "en-NZ", "en-PH", "en-SG", "en-ZA", "en-TT", "en-GB",
"en-US", "en-ZW", "es-CR", "es-DO", "es-EC", "es-SV", "es-GT",
"es-HN", "es-MX", "es-NI", "es-PA", "es-PY", "es-PE", "es-PR",
"es-ES", "es-US", "es-UY", "es-VE" };
private static readonly List<string> _cultures = new List<string> {
"en-US", // first culture is the DEFAULT
"es", // Spanish NEUTRAL culture
"ar" // Arabic NEUTRAL culture
};
public static bool IsRightToLeft()
{
return
System.Threading.Thread.CurrentThread
.CurrentCulture.TextInfo.IsRightToLeft;
}
public static string GetImplementedCulture(string name)
{
// make sure it's not null
if (string.IsNullOrEmpty(name))
return GetDefaultCulture(); // return Default culture
if (_validCultures.Where(c => c.Equals(name,
StringComparison.InvariantCultureIgnoreCase)).Count() == 0)
return GetDefaultCulture(); // return Default if invalid
if (_cultures.Where(c => c.Equals(name,
StringComparison.InvariantCultureIgnoreCase)).Count() > 0)
return name; // accept it
var n = GetNeutralCulture(name);
foreach (var c in _cultures)
if (c.StartsWith(n))
return c;
return GetDefaultCulture(); // return Default if no match
}
public static string GetDefaultCulture()
{
return _cultures[0]; // return Default culture
}
public static string GetCurrentCulture()
{
return Thread.CurrentThread.CurrentCulture.Name;
}
public static string GetCurrentNeutralCulture()
{
return GetNeutralCulture(Thread.CurrentThread.CurrentCulture.Name);
}
public static string GetNeutralCulture(string name)
{
if (name.Length < 2)
return name;
return name.Substring(0, 2);
}
}
}
Controllers/BaseController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using xxxUSA.Helpers;
namespace xxxUSA.Controllers
{
public class BaseController : Controller
{
protected override IAsyncResult BeginExecuteCore(
AsyncCallback callback, object state)
{
string cultureName = null;
// Attempt to read the culture cookie from Request
HttpCookie cultureCookie = Request.Cookies["_culture"];
if (cultureCookie != null)
cultureName = cultureCookie.Value;
else
cultureName = Request.UserLanguages != null &&
Request.UserLanguages.Length > 0 ? Request.UserLanguages[0]
: null; // obtain it from HTTP header AcceptLanguages
// Validate culture name
cultureName = CultureHelper.GetImplementedCulture(cultureName);
// Modify current thread's cultures
Thread.CurrentThread.CurrentCulture = new
System.Globalization.CultureInfo(cultureName);
Thread.CurrentThread.CurrentUICulture =
Thread.CurrentThread.CurrentCulture;
return base.BeginExecuteCore(callback, state);
}
}
}
OK, now we get into where I have modified some things. I will comment on anything I added
Controllers/HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using xxxUSA.Helpers;
using xxxUSA.Models;
namespace xxxUSA.Controllers
{
public class HomeController : BaseController
{
ApplicationDbContext _db = new ApplicationDbContext();
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View();
}
//I ADDED THIS LAST PARAMETER
public ActionResult SetCulture(string culture, string returnUrl)
{
// Validate input
culture = CultureHelper.GetImplementedCulture(culture);
// Save culture in a cookie
HttpCookie cookie = Request.Cookies["_culture"];
if (cookie != null)
cookie.Value = culture; // update cookie value
else
{
cookie = new HttpCookie("_culture");
cookie.Value = culture;
cookie.Expires = DateTime.Now.AddYears(1);
}
Response.Cookies.Add(cookie);
//THIS WORKS
return Redirect(returnUrl);
//THIS DOES NOT
if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Now for the code on the Home Page
Views/Home/Index.cshtml
#{
var culture = System.Threading.Thread.CurrentThread
.CurrentUICulture.Name.ToLowerInvariant();
ViewBag.Title = culture;
}
//I ADDED THIS LAST PARAMETER
#helper selected(string c, string culture, string returnUrl)
{
if (c == culture)
{
#:checked="checked"
}
}
#using (Html.BeginForm("SetCulture", "Home"))
{
#Resources.ChooseYourLanguage
<input name="culture" id="en-us" value="en-us"
//I ADDED THIS LAST PARAMETER "About"
type="radio" #selected("en-us", culture, "About") /> English
<input type="Hidden" name="returnUrl" value="About" />
<input name="culture" id="es" value="es"
//I ADDED THIS LAST PARAMETER "About"
type="radio" #selected("es", culture, "About") /> Español
}
//LOTS OF STUFF LOADS HERE LIKE RESOURCE REFERENCES, GRAPHICS, CONTENT,
//NOT IMPORTANT FOR THE IMPLEMENTATION REMOVED FOR BREVITY
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
(function ($) {
$("input[type = 'radio']").click(function () {
$(this).parents("form").submit(); // post form
});
})(jQuery);
</script>
}
So the reason I added the "About" was so if I got it to work, It would redirect to the "About" Action instead of back to the same homepage. It doesn't work though.
Can I not overload the checkboxes #Selected Method the way I have?
Also, NOT IMPORTANT NOW, but what if I wanted to add this to other views from other controllers, Could I include another parameter to designate the controller and action it needs to return to so that I don't have to repeat the code in each controller?
I have contacted Nadeem on twitter and he said he would check it out and try and help. I really appreciate his work and seems like a very kind fellow.. Thanks in advance for simply helping in any capacity!
OK so I have a products/Ingredients page where I have stuff coming from the database, here how I hacked that to show the right field from the database. This is a total HACK BEWARE.
Views/Products.cshtml
#model IEnumerable<xxxUSA.Models.Ingredient>
#{
var culture = System.Threading.Thread.CurrentThread
.CurrentUICulture.Name.ToLowerInvariant();
ViewBag.Title = culture;
}
#helper selected(string c, string culture)
{
if (c == culture)
{#:checked="checked"}
}
<div class="row">
<div class="large-12 columns">
#using(Html.BeginForm("SetCulture", "Ingredient"))
{
<div class="row">
<div class="large-6 columns">
<label>#Resources.ChooseYourLanguage</label>
<input type="Hidden" name="returnUrl" value="/Prodcuts/" />
<input name="culture" id="en-us" value="en-us" type="radio"
#selected("en-us", culture) /> English
<input name="culture" id="es" value="es" type="radio"
#selected("es", culture) /> Español
</div>
</div>
}
#{ViewBag.Culture = System.Threading.Thread.CurrentThread
.CurrentUICulture.Name.ToLowerInvariant();}
//Here is where the conditional logic hack I use to show one field
//or another from the database based on culture
#if (ViewBag.Culture == "en-us") {
#Html.DisplayFor(modelItem => item.IngredientNameEn)
} else {
#Html.DisplayFor(modelItem => item.IngredientNameEs) }
Basically using that conditional logic anywhere I have data that has a spanish or english version. it's hacky as hell though.
Try this:
public ActionResult SetCulture(string culture, string returnUrl)
{
// Validate input
culture = CultureHelper.GetImplementedCulture(culture);
// Save culture in a cookie
HttpCookie cookie = Request.Cookies["_culture"];
if (cookie != null)
cookie.Value = culture; // update cookie value
else
{
cookie = new HttpCookie("_culture");
cookie.Value = culture;
cookie.Expires = DateTime.Now.AddYears(1);
}
Response.Cookies.Add(cookie);
if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
I'm also using Nadeem's i18n solution in a project. The way you switch the culture in this project is through clicking on flags (anchor tags in image tags). I added a returnUrl and ended up with a redirect loop. To fix the redirect loop issue, I made a few changes to the code and ended up with this code:
File: BaseController.cs (added this method)
public ActionResult SetCulture(string culture, string returnUrl)
{
// Validate input
culture = CultureHelper.GetImplementedCulture(culture);
RouteData.Values["culture"] = culture;
// Save culture in a cookie
HttpCookie cookie = Request.Cookies["_culture"];
if (cookie != null)
{
// update cookie value
cookie.Value = culture;
}
else
{
cookie = new HttpCookie("_culture");
cookie.Value = culture;
cookie.Expires = DateTime.Now.AddYears(1);
}
Response.Cookies.Add(cookie);
return Redirect(returnUrl);
}
File: _layout.cshtml (flags for selecting culture):
#{ var daDkUrl = Url.Action("setculture", "base", new { culture = "da-DK", returnUrl = Request.RawUrl }); }
<a href="#daDkUrl">
<img src="~/content/images/flag_da.gif" width="16" height="11" alt="Dansk" />
</a>
|
#{ var enUsUrl = Url.Action("setculture", "base", new { culture = "en-US", returnUrl = Request.RawUrl }); }
<a href="#enUsUrl">
<img src="~/content/images/flag_en.gif" width="16" height="11" alt="English" />
</a>
Finally, ensure your controllers inherit from BaseController.cs.
public class TestController : BaseController
{
//Code
}

MVC3 Display a dropdown list from one datasource and save to another datasource

I'm getting back to an MVC3 project after a 3 month hiatus. I need to display a drop down list that pulls from Database A, but saves to Database B. The property I need to persist is the NAICS/SIC code. Right now I just provide the user a text box to key in freeform text. So, I have the mechanics of that down. But instead it should provide only a valid list of codes from a source database.
The tricky thing to is I'm using a custom model binder to generate my ViewModels on the fly, so I don't have a distinct .cshtml file to customize.
[Serializable]
public class Step4ViewModel : IStepViewModel
{
public Step4ViewModel()
{
}
//load naics codes from somewhere
[Display(Name = "Describe the nature of your business.")]
public String NatureOfBusiness { get; set; }
[Display(Name="NAICS/SIC CODE")]
public String BusinessTypeCode { get; set; }
Tricky ViewModel
#using Microsoft.Web.Mvc;
#using Tangible.Models;
#model Tangible.Models.WizardViewModel
#{
var currentStep = Model.Steps[Model.CurrentStepIndex];
var progress = ((Double)(Model.CurrentStepIndex) / Model.Steps.Count) * 100;
}
<script type="text/javascript">
$(function () {
$("#progressbar").progressbar({
value: #progress
});
});
</script>
<div id="progressbar" style="height:20px;">
<span style="position:absolute;line-height:1.2em; margin-left:10px;">Step #(Model.CurrentStepIndex + 1) out of #Model.Steps.Count</span>
</div>
#Html.ValidationSummary()
#using (Html.BeginForm())
{
#Html.Serialize("wizard", Model)
#Html.Hidden("StepType", Model.Steps[Model.CurrentStepIndex].GetType())
#Html.EditorFor(x => currentStep, null, "")
if (Model.CurrentStepIndex > 0)
{
<input type="submit" value="Previous" name="prev" />
}
if (Model.CurrentStepIndex < Model.Steps.Count - 1)
{
<input type="submit" value="Save & Continue" name="next" />
}
else
{
<input type="submit" value="Finish" name="finish" />
}
#*<input type="submit" value="Save" name="Save" />*#
}
Controller
[HttpPost]
public ActionResult Index([Deserialize] WizardViewModel wizard, IStepViewModel step)
{
wizard.Steps[wizard.CurrentStepIndex] = step;
if (ModelState.IsValid)
{
//Always save.
var obj = new dr405();
//wire up to domain model;
foreach (var s in wizard.Steps)
{
Mapper.Map(s,obj,s.GetType(), typeof(dr405));
}
using (var service = new DR405Service())
{
//Do something with a service here.
service.Save(db, obj);
}
if (!string.IsNullOrEmpty(Request["next"]))
{
wizard.CurrentStepIndex++;
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
wizard.CurrentStepIndex--;
}
else
{
return View("Upload", obj);
}
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
wizard.CurrentStepIndex--;
}
return View(wizard);
}
WizardViewModel
[Serializable]
public class WizardViewModel
{
public String AccountNumber { get; set; }
public int CurrentStepIndex { get; set; }
public Boolean IsInitialized { get { return _isInitialized; } }
public IList<IStepViewModel> Steps { get; set; }
private Boolean _isInitialized = false;
public void Initialize()
{
try
{
Steps = typeof(IStepViewModel)
.Assembly.GetTypes().Where(t => !t.IsAbstract && typeof(IStepViewModel).IsAssignableFrom(t)).Select(t => (IStepViewModel)Activator.CreateInstance(t)).ToList();
_isInitialized = true;
//rewrite this. get the profile and wire them up or something.
this.AccountNumber = Tangible.Profiles.DR405Profile.CurrentUser.TangiblePropertyId;
}
catch (Exception e)
{
_isInitialized = false;
}
}
}
You can specify a template for a specific property on your view model by adding the UIHint attribute to the field. Since your view calls EditorFor on the model it will use the template you specified with UIHint.
BusinessTypeDropdown.ascx - (placed in Views/Shared/EditorTemplates
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<% var businessTypes = ViewData["businessTypes"] as IEnumerable<string>; %>
<%= Html.DropDownListFor(m => m , new SelectList(businessTypes, Model))%>
In your View Model
[Serializable]
public class Step4ViewModel : IStepViewModel
{
public Step4ViewModel()
{
}
//load naics codes from somewhere
[Display(Name = "Describe the nature of your business.")]
public String NatureOfBusiness { get; set; }
[Display(Name="NAICS/SIC CODE")][UIHint("BusinessTypeDropdown")]
public String BusinessTypeCode { get; set; }
Then in your controller just set ViewData["businessTypes"] to your list of business types.
Without understanding your "tricky" view model code, it will be hard to make helpful suggestions.
However, there shouldn't be much problem here. You need to somehow create your dropdown list in yoru view, and populate it from data passed from your controller.
All the work happens in your controller. Populate your list or IEnumerable or whatever data source from your first database, then in your post handler save the selection it to your second database (the second part should not be much different from what you already have).

Resources