I am using this code in mVC2 and it is working Fine for me. But when i convert it into mvc3 this code give me error. Please tell me how i convert it into mvC3. The code is
<% Html.Grid(Model.MemberPagedList).Columns(column => {
column.For(x => x.Id).Named("Id");
column.For(x => x.message).Named("Message").Action(p =>
{ %>
<td> some image tag here
</td>
<td style="display: none; " id =<%= p.Id%>>
<%= p.LogMessage %>
</td>
<% });
}).RowStart((p,row) => {
if (row.IsAlternate) { %>
<tr >
<% } else { %>
<tr>
<% }
}).Sort(Model.GridSortOptions).Attributes(#class => "table-list").Render(); %>
I am Replacing <% %> with # But it is not working. I am not able to understand how i write Html Code ie <td>.....</td>
<td style="display: none;" id=<%= p.Id%>>
<%= p.LogMessage %>
</td>
in mvc3
You could use a custom column to add an image to an MVCContrib Grid:
#(Html
.Grid<MyViewModel>(Model.MemberPagedList)
.Columns(column =>
{
column.For(x => x.Id);
column.For(x => x.LogMessage);
column
.Custom(
#<text>
<span>#item.LogMessage</span>
<img src="#Url.Action("image", new { id = item.Id })" alt="" />
</text>
)
.Named("Message");
})
.Sort(Model.GridSortOptions)
.Attributes(new Hash(#class => "table-list"))
)
Related
I have a dropdown box to chose the number of tickets that one wants to buy. I want to update the fields after it to reflect the value once it is clicked. Here is a snippet of my form currently:
<%= form_for :transaction, :url => new_transaction_path(:event_id => #event.id), :method => 'GET' do |f| %>
<table style="width:100%">
<tr style="border-bottom: 1px solid #999999">
<td><h4>Number of Guests</h4></td>
<td>
<%= f.select(:quantity, (1..20))%>
</td>
</tr>
<tr style="border-bottom: 1px solid #999999">
<!-- replace (1) with the value from the f.select dropdown -->
<td><h4><%= #original_event_price %> x (1) guest(s)</h4></td>
</tr>
</table>
<%= f.submit 'Request to Book', class: 'button mt1 btn-request-to-book' %>
<% end %>
I want to replace (1) with the value from the f.select dropdown in the last table row to the value of guests that the user chooses.
EDIT WITH WORKING SOLUTION
<%= form_for :transaction, :url => new_transaction_path(:event_id => #event.id), :method => 'GET' do |f| %>
<table style="width:100%">
<tr style="border-bottom: 1px solid #999999">
<td><h4>Number of Guests</h4></td>
<td>
<%= f.select :quantity, (1..20), {}, { :onChange=>'mytest()', :id=>'quantitySelect' } %>
</td>
</tr>
<tr style="border-bottom: 1px solid #999999">
<!-- replace (1) with the value from the f.select dropdown -->
<td><h4><%= #original_event_price %> x (1) guest(s)</h4></td>
</tr>
</table>
<%= f.submit 'Request to Book', class: 'button mt1 btn-request-to-book' %>
<% end %>
SCRIPT
<script type="text/javascript">
function mytest() {
var quantity = $('#quantitySelect').val();
$('#quantityRow').html("<h4><%= #original_event_price %> x (" + quantity + ") guest(s)");
}
</script>
Problem : How to load value in other field based on drop-down selection
Solution:
<div class="field form-group">
<%= form.label :grade %>
<%= form.select(:grade, options_for_select(['A', 'B', 'C', 'D', 'E', 'F']), {:include_blank => 'Select Grade'}, class:"form-control", placeholder:"Grade", onchange: "loadRemarksBasedOnGrade()") %>
</div>
<div class="field form-group">
<%= form.label :remarks %>
<%= form.text_field :remarks, class:"form-control", placeholder:"Remarks", readonly: true %>
</div>
JavaScript :
<script type="text/javascript">
function loadRemarksBasedOnGrade() {
var grades = [];
grades['A'] = "Excellent";
grades['B'] = "Very Good";
grades['C'] = "Good";
grades['D'] = "Average";
grades['E'] = "Below average";
grades['F'] = "Failed";
let grade = document.getElementById("student_grade");
if(grades[grade.value] !== undefined) {
document.getElementById("student_remarks").value = grades[grade.value];
} else {
document.getElementById("student_remarks").value = "";
}
}
</script>
Note: So onchnage event loadRemarksBasedOnGrade update value based on id.
You can do this with jQuery:
Let's add an id: "quantitySelect" on the quantity field
Let's also add an id: "quantityRow" on the td field
$(function(){
$('.quantitySelect').change(function(e){
e.preventDefault();
var quantity = $('.quantitySelect').val();
$('.quantityRow').html("<h4><%= #original_event_price %> x (" + quantity + ") guest(s)");
});
});
You can also add if checks to see if the quantity is > 1 and append the word guest to guests.
I have a MultiSelect belongs to Kendo ListView EditorTemplates. When I want to submit selected MultiSelect values, I got list of items selected, but all populated with 0 value. I cant get correct value of selected items.
Here is my ListView:
#(Html.Kendo().ListView<esCMS.Modules.C2C.Domain.c2cFieldRangeList>()
.Name("listView")
.TagName("div")
.ClientTemplateId("template")
.DataSource(dataSource => dataSource
.Model(model => model.Id(x => x.FieldRangeID))
.PageSize(6)
.Create(create => create.Action("AddRange", "Field"))
.Update(update => update.Action("UpdateRange", "Field"))
.Read(read => read.Action("ReadRange", "Field", new { id = Model.FieldID }))
))
And here is my EditorTemplates:
<table>
<tr>
<td>
#Html.LabelFor(x => x.RangeValue)
</td>
<td>
:
</td>
<td>
#Html.TextBoxFor(x => x.RangeValue, new { #class = "k-textbox", style = "width:180px" })
<span data-for="RangeValue" class="k-invalid-msg"></span>
</td>
</tr>
<tr>
<td>
#Html.LabelFor(x => x.SelectedValues)
</td>
<td>
:
</td>
<td>
#(Html.Kendo().MultiSelectFor(x=> x.SelectedValues)
.HtmlAttributes(new { style = "width:180px" })
.BindTo(new SelectList(ViewBag.Fields, "FieldID", "Title")))
</td>
</tr></table>
Edit: ViewBag.Fields contains List of c2cFieldList model and I expect to get List of FieldID when I submit view.
ViewBag.Fields = Entities.c2cField.Where(x => !x.IsGeneral && !x.IsTemp).Select(x => new c2cFieldList { Title = x.Title, FieldID = x.FieldID});
Any advice will be helpful.
I am developing a MVC 3 Razor app and I'm having issues when I click the back button in the browser. My application workflow:
Select a facility from a dropdown list
A WebGrid gets populated with a list of the facility's buildings.
Click an image to edit a building
Click the browser's back button and the dropdown list in step 1 appears without the CSS formatting. If I click F5 to refresh then everything resets and the CSS formatting is back.
I'm using VS2010 and the ASP.NET development server with IE9 as the default browser. I have added the OutputCache attribute to every ActionResult in the controller.
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
Here's my link in the WebGrid built from a PartialView
grid.Column(header: "",
format: #<text><a href="#Url.Action("Edit", "BuildingModels", new { #id = item.FACInventoriesId })"><img src="#Url.Content("~/Content/images/edit.png")"
alt='Edit' title='Edit' border='0'/></a></text>)
How do I get a browser to show the WebGrid (step 2) when the back button is click from editing a building (step 4)? Also any ideas why the CSS formatting is missing when I click the back button?
Here's the Controller code:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ViewResult Index()
{
ViewBag.Systems = buildingsVM.GetSystemsList();
return View();
}
[HttpPost]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult GetFacilityDetails(int systemId, string facilityId)
{
try
{
ViewBag.Systems = buildingsVM.GetSystemsList();
var facility = buildingsVM.GetFacilityDetails(systemId, facilityId);
facility.Buildings = buildingsVM.GetFacilityBuildings(systemId, facilityId);
var bldgsHtml = ViewsUtility.RenderPartialViewToString(this, "_Buildings", facility.Buildings);
TempData["CurrentFacility"] = facility;
return Json(new { ok = true, facdata = facility, bldgs = bldgsHtml, message = "ok" });
}
catch (Exception ex)
{
return Json(new { ok = false, message = ex.Message });
}
}
[HttpPost]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult GetSystemFacilities(int systemId)
{
try
{
var facilities = buildingsVM.GetFacilitesBySystemId(systemId);
return Json(new { ok = true, data = facilities, message = "ok" });
}
catch (Exception ex)
{
return Json(new { ok = false, message = ex.Message });
}
}
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult Edit(int id)
{
var facility = TempData["CurrentFacility"] as FacilityModel;
return View(buildingsVM.GetBuilding(id));
}
Code from Partial View:
#model IEnumerable<COPSPlanningWeb.Models.BuildingModel>
<!-- Current Buildings from partial view -->
#{
if (Model != null && Model.Count() > 0)
{
var grid = new WebGrid(rowsPerPage: 50, defaultSort: "BuildingNumber"); //ajaxUpdateContainerId: "tabs-2",
grid.Bind(Model, rowCount: Model.Count(), autoSortAndPage: false);
grid.Pager(WebGridPagerModes.All);
#grid.GetHtml(
tableStyle: "webgridDisplay",
alternatingRowStyle: "alt",
columns: grid.Columns(
//grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { EmployeeID = item.EmployeeID, ContactID = item.ContactID })),
grid.Column("BuildingNumber", header: "Building Number", style: "webgridDisplayCenter"),
grid.Column("ConstructionDate", header: "Construction Date", format: #<text>#item.ConstructionDate.ToString("MM/dd/yyyy")</text>),
grid.Column("ExtSquareFeet", header: "Exterior Sq. Ft.", format: (item) => string.Format("{0:n0}", item.ExtSquareFeet)),
grid.Column("IntSquareFeet", header: "Interior Sq. Ft.", format: (item) => string.Format("{0:n0}", item.IntSquareFeet)),
grid.Column("IU_Avail", header: "IU Available"),
grid.Column("SpaceAvail", header: "Space Available"),
grid.Column("FixedAssetValue", header: "Fixed Asset Value", format: (item) => string.Format("{0:C}", item.FixedAssetValue)),
grid.Column("FixedEquipValue", header: "Fixed Equipment Value", format: (item) => string.Format("{0:C}", item.FixedEquipValue)),
grid.Column(header: "",
format: #<text><a href="#Url.Action("Edit", "BuildingModels", new { #id = item.FACInventoriesId })"><img src="#Url.Content("~/Content/images/edit.png")"
alt='Edit' title='Edit' border='0'/></a></text>),
grid.Column(header: "",
format: #<text><a href="#Url.Action("Delete", "BuildingModels", new { #id = item.FACInventoriesId })"><img src="#Url.Content("~/Content/images/trash.png")"
alt='Delete' title='Delete' border='0'/></a></text>)
))
}
}
Code from Edit view:
#model COPSPlanningWeb.Models.BuildingModel
#{
ViewBag.Title = "Add/Edit Inventory";
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<table style="width: 100%;" class="display">
#Html.HiddenFor(model => model.FacilityId)
#Html.HiddenFor(model => model.FACInventoriesId)
<tr>
<th colspan="2" style="text-align: left;">
Building Information - Edit Inventory
</th>
</tr>
<tr>
<td class="fieldlabel">
Facility Name
</td>
<td class="fielddata">
</td>
</tr>
<tr>
<td class="fieldlabel">
Building Number
</td>
<td class="fielddata">
#Html.EditorFor(model => model.BuildingNumber)
#Html.ValidationMessageFor(model => model.BuildingNumber)
</td>
</tr>
<tr>
<td class="fieldlabel">
Construction Date
</td>
<td class="fielddata">
#Html.EditorFor(model => model.ConstructionDate, "DateTime")
#Html.ValidationMessageFor(model => model.ConstructionDate)
</td>
</tr>
<tr>
<td class="fieldlabel">
Exterior Sq. Ft.
</td>
<td class="fielddata">
#Html.EditorFor(model => model.ExtSquareFeet)
#Html.ValidationMessageFor(model => model.ExtSquareFeet)
</td>
</tr>
<tr>
<td class="fieldlabel">
Interior Sq. Ft.
</td>
<td class="fielddata">
#Html.EditorFor(model => model.IntSquareFeet)
#Html.ValidationMessageFor(model => model.IntSquareFeet)
</td>
</tr>
<tr>
<td class="fieldlabel">
IU Available
</td>
<td class="fielddata">
#Html.EditorFor(model => model.IU_Avail)
#Html.ValidationMessageFor(model => model.IU_Avail)
</td>
</tr>
<tr>
<td class="fieldlabel">
Space Available
</td>
<td class="fielddata">
#Html.EditorFor(model => model.SpaceAvail)
#Html.ValidationMessageFor(model => model.SpaceAvail)
</td>
</tr>
<tr>
<td class="fieldlabel">
Fixed Asset Value
</td>
<td class="fielddata">
#Html.EditorFor(model => model.FixedAssetValue)
#Html.ValidationMessageFor(model => model.FixedAssetValue)
</td>
</tr>
<tr>
<td class="fieldlabel">
Fixed Equipment Value
</td>
<td class="fielddata">
#Html.EditorFor(model => model.FixedEquipValue)
#Html.ValidationMessageFor(model => model.FixedEquipValue)
</td>
</tr>
<tr>
<td class="fieldlabel">
Total Fixed Asset Value
</td>
<td class="fielddata">
#Html.EditorFor(model => model.TotalFixedAssetValue)
#Html.ValidationMessageFor(model => model.TotalFixedAssetValue)
</td>
</tr>
<tr>
<td class="fieldlabel">
Total Fixed Equipment Value
</td>
<td class="fielddata">
#Html.EditorFor(model => model.TotalFixedEquipValue)
#Html.ValidationMessageFor(model => model.TotalFixedEquipValue)
</td>
</tr>
<tr>
<td colspan="2">
<table class="display" style="text-align: center;">
<tr>
<td>
#Html.ActionLink("Add/Edit Spaces", "Index")
</td>
<td>
<input type="submit" value="Save Changes" class="button" />
</td>
<td>
#Html.ActionLink("Back to Buildings List", "Index")
</td>
</tr>
</table>
</td>
</tr>
</table>
}
When I click the back button from the Edit view I expected to see the WebGrid again (building list), but instead I get the first view without any CSS formatting.
Thanks to Luis I was able to resolve the CSS formatting issue, but I'm still not seeing the WebGrid when I click the back button. I'm using JSON to populate the WebGrid could this be the problem? Should I use a form post after the item in the dropdown has been selected?
Something similar happened to me making an app for the intranet... but hey cheer up, at least your company uses IE9... I had to make miracles trying to make a MVC3 Razor app with JQuery work with IE7...
Ok now to what's important, I had a similar issue with the cache of IE, it appears that the cache of this browser works "differently" from the normal-new-age browsers, you could try this:
Press F12 and go to the tab Cache and check Always refresh from server
Then check if everything works as it should do, if it does, tell your network administrator to make a new policy for all the IE browsers that are going to use this new app you're making.
Also check this https://superuser.com/questions/81182/how-to-force-internet-explorer-ie-to-really-reload-the-page
Hope it helps!
You need to add the Location to the attribute to get this to work with IE9
[OutputCache(Location = OutputCacheLocation.ServerAndClient, NoStore = true, Duration = 0, VaryByParam = "None")]
I am using MVC 3 and Razor, attempting to post a form back to a controller from a telerik window (telerik.window.create) that loads a partial view. Im not sure how to post this so ill just post the code in order of execution and explain it as I go.
First an anchor is clicked, and onClick calls:
function showScheduleWindow(action, configId) {
var onCloseAjaxWindow = function () { var grid = $("#SubscriptionGrid").data("tGrid"); if (grid) { grid.rebind(); } };
CreateAjaxWindow("Create Schedule", true, false, 420, 305, "/FiscalSchedule/" + action + "/" + configId, onCloseAjaxWindow);
}
And the CrateAjaxWindow method:
function CreateAjaxWindow(title, modal, rezible, width, height, url, fOnClose) {
var lookupWindow = $.telerik.window.create({
title: title,
modal: modal,
rezible: rezible,
width: width,
height: height,
onClose: function (e) {
e.preventDefault();
lookupWindow.data('tWindow').destroy();
fOnClose();
}
});
lookupWindow.data('tWindow').ajaxRequest(url);
lookupWindow.data('tWindow').center().open();
}
Here is the partial view that is being loaded:
#model WTC.StatementAutomation.Web.Models.FiscalScheduleViewModel
#using WTC.StatementAutomation.Model
#using WTC.StatementAutomation.Web.Extensions
#using (Html.BeginForm("Create", "FiscalSchedule", FormMethod.Post, new { id = "FiscalScheduleConfigForm" }))
{
<div id="FiscalScheduleConfigForm" class="stylized">
<div class="top">
<div class="padding">
Using fiscal year end: #Model.FiscalYearEnd.ToString("MM/dd")
</div>
<div class="padding Period">
<table border="0">
<tr>
<th style="width: 120px;"></th>
<th>Effective Date</th>
<th>Next Run</th>
<th>Start From Previous</th>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasMonthly)
<label>Monthly</label>
</td>
<td>
#{ var month = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.Monthly);}
#month.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#month.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(month.HasRun ? Html.CheckBoxFor(m => month.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => month.BaseSchedule.StartFromPreviousCycle))
</td>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasQuarterly) Quarterly
</td>
<td>
#{ var quarter = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.Quarterly);}
#quarter.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#quarter.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(quarter.HasRun ? Html.CheckBoxFor(m => quarter.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => quarter.BaseSchedule.StartFromPreviousCycle))
</td >
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasAnnual) Annual
</td>
<td>
#{ var annual = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.Annual);}
#annual.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#annual.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(annual.HasRun ? Html.CheckBoxFor(m => annual.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => annual.BaseSchedule.StartFromPreviousCycle))
</td>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasSemiAnnual) Semi-annual
</td>
<td>
#{ var semi = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.SemiAnnual);}
#semi.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#semi.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(semi.HasRun ? Html.CheckBoxFor(m => semi.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => semi.BaseSchedule.StartFromPreviousCycle))
</td>
</tr>
</table>
</div>
<div class="padding StartDay">
<span>Run on day:</span>
#Html.TextBoxFor(model => model.StartDay)
<span>of every period.</span>
</div>
</div>
<div class="bottom">
<div class="padding">
<div style="float: left;">
#if (Model.ShowSuccessSave)
{
<div id="successSave" class="label">Changes saved succesfully</div>
}
#Html.ValidationSummary(true)
#Html.HiddenFor(x => x.SubscriptionId)
#Html.HiddenFor(x => x.DeliveryConfigurationId)
#Html.HiddenFor(x => x.FiscalYearEnd)
</div>
<a id="saveSchedule" class="btn" href="">Save</a>
</div>
</div>
</div>
}
<script type="text/javascript">
$(function () {
$('a#saveSchedule').click(function () {
$(this).closest("form").submit();
return false;
});
});
</script>
And finally the controller method:
[HttpPost]
public ActionResult Create(FormCollection formValues, int subscriptionId, int deliveryConfigurationId, int startDay, DateTime fiscalYearEnd)
{
if (ModelState.IsValid)
{
var selectedSchedules = GetCheckedSchedulesFromForm(formValues);
var startFromPrevious = GetFromPreviouSelections(formValues);
this.AddModelErrors(_fiscalScheduleService.AddUpdateSchedules(selectedSchedules, subscriptionId, deliveryConfigurationId, startDay, startFromPrevious));
}
return new RenderJsonResult { Result = new { success = true, action = ModelState.IsValid ? "success" : "showErrors",
message = this.RenderPartialViewToString("_FiscalScheduleConfigForm",
BuildResultViewModel(deliveryConfigurationId, subscriptionId, fiscalYearEnd, ModelState.IsValid)) } };
}
As you can see I am using jQuery to post back to the controller, which I have done on several occasions in the applicaiton, this seems to work fine normally. But with this form, for some reason it is not posting back or stepping into the Create method at all. I am speculating that it has something to do with the parameters on the controller method. But I am fairly new to MVC (coming from ASP.NET world) so Im not really sure what I am doing wrong here. Any help would be greately appreciated!
I was able to get it to post to the controller by modifying the textboxfor for the startDay:
Changed from:
#Html.TextBoxFor(model => model.StartDay)
To:
#Html.TextBoxFor(model => model.StartDay, new { id = "startDay" })
My guess is that you're running on a virtual directory in IIS? That url you're generating is likely the culprit.
Hit F12, check out the network tab (and enable tracing) and see what it's trying to request.
Instead of building the link through text, why not use #Url.Action()? You could store this in an attribute on the a tag (like in an attribute called data-url, for example) and then use that info to make your call. It's pretty easy to pull out the attribute with jQuery, something like this:
$('.your-link-class').click(function(){
var url = $(this).attr('data-url');
// proceed with awesomesauce
});
Would something like that work for you?
[shameless self plug] As far as the controller action signature goes, you might want to look into model binding if you can. One simple class and many of your headaches will go away. You can read more here, read the parts on model binding. There are downloadable samples for different approaches.
Cheers.
I have a pretty simple MVC 2 form. It has two dropdowns, user and role. The employee dropdown passes validation, and the role dropdown does not, regardless of what I select. There is no default "empty" option although I plan to implement one, which is why I need the validation to work. It fails both client and server validation. I just can't see why one would work and one does not!
The Form:
<% using (Html.BeginForm()) {%>
<%:Html.ValidationSummary(true) %>
<%:Html.EditorFor(model => model.User, new { AllEmployees = Model.AllEmployees, RoleList = Model.RoleList })%>
<p>
<input type="submit" value="Add New User" />
</p>
<% } %>
<% Html.EndForm(); %>
The Editor Template:
<tr>
<td>
<div class="editor-label">
<%: Html.LabelFor(model => model.UserId) %>
<%: Html.RequiredMarkFor(model => model.UserId) %>
</div>
</td>
<td>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.UserId, new SelectList(ViewData["AllEmployees"] as IEnumerable, "UserId", "DisplayName", Model.UserId)) %>
<%: Html.ValidationMessageFor(model => model.UserId>
</div>
</td>
</tr>
<tr>
<td>
<div class="editor-label">
<%: Html.LabelFor(model => model.AccessLevel)%>
<%: Html.RequiredMarkFor(model => model.AccessLevel)%>
</div>
</td>
<td>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.AccessLevel, new SelectList(ViewData["RoleList"] as IEnumerable, Model.AccessLevel))%>
<%: Html.ValidationMessageFor(model => model.AccessLevel)%>
</div>
</td>
</tr>
The Metadata:
[DisplayName("Employee")]
[Required(ErrorMessage = "Please select an employee.")]
[StringLength(8, ErrorMessage = "User Id must be less than 8 characters.")]
[DisplayFormat(ConvertEmptyStringToNull = false,
HtmlEncode = true)]
[DataType(DataType.Text)]
public object UserId { get; set; }
// Validation rules for Access Level
[DisplayName("Role")]
[Required(ErrorMessage = "Please select the role for this user.")]
[StringLength(15, ErrorMessage = "Role must be under 15 characters.")]
[DisplayFormat(ConvertEmptyStringToNull = false,
HtmlEncode = true)]
[DataType(DataType.Text)]
public object AccessLevel { get; set; }
The Get Action:
List<String> roles = (from o in txDB.Users
select o.AccessLevel).Distinct().ToList();
var viewModel = new UserViewModel
{
User = new User(),
AllEmployees = empList,
RoleList = roles
};
return View(viewModel);
The Post Action:
[HttpPost]
[AuthorizeAttribute(Roles="Administrator")]
public ActionResult Create(User user)
{
if(!ModelState.IsValid)
{
//ModelState is invalid
return View(new User());
}
try
{
//do stuff
}
}
The Required Helper Method (from Define markup for [Required] fields in View in ASP.NET MVC 2.0):
public static string RequiredMarkFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
if(ModelMetadata.FromLambdaExpression(expression, helper.ViewData).IsRequired)
return "*";
else
return string.Empty;
}
Post method should be as follows to get Server side validation...
[HttpPost]
[AuthorizeAttribute(Roles="Administrator")]
public ActionResult Create(User user)
{
if(!TryUpdateModel(user))
{
// Model is INVALID
return View(user);
}
else
{
// ModelState is VALID
// Do stuff
}
}
The else might be redundant depending on what you're doing but that should get you going.
In the view above your <% using Html.BeginForm() %> you need
<% Html.EnableClientValidation(); %>
You also need to reference the scripts, MicrosoftAjax and MicrosoftMvcValidation I think
First of all: You have two closing form tags
If you use
<% using (Html.BeginForm()) {%>
<% } %>
you dont need to use this
<% Html.EndForm(); %>
Regarding your validation problem you are using an editor only for your User property, which is the only one that get binded by the model binder
<%:Html.EditorFor(model => model.User, new { AllEmployees = Model.AllEmployees, RoleList = Model.RoleList })%>
Try to replace the previous code with an EditorForModel as your Editor Template is for a model class.
So your form should change in
<% using (Html.BeginForm()) {%>
<%:Html.ValidationSummary(true) %>
<table>
<%:Html.EditorForModel()%>
</table>
<p>
<input type="submit" value="Add New User" />
</p>
<% } %>
and you're done!