Getting the parent model ID when adding a child entry in MVC 3 w/razor? - asp.net-mvc-3

So in a one to many relational database structured app, you of course need to be able to add multiple child entries for a parent... So let's say that you have a User, and the User can have one Profile, but each profile can have multiple Projects, and of course Projects consist of multiple child tables, such as for example, ProjectCodeSamples, being one of them...
So obviously to add a new ProjectCodeSample, it requires the ProjectID that it belongs to (as the foreign key)... So in the AddCodeSample View, how do you get that value, the value of the ProjectID, so that you can put it in a hidden field and pass it?
Here is the ProjectCodeSample Model:
namespace ProDevPortMVC3
{
using System;
using System.Collections.Generic;
public partial class ProjectCodeSample
{
public int ProjectCodeSampleID { get; set; }
public int ProjectID { get; set; }
public string ProjectCodeSampleContent { get; set; }
public string ProjectCodeSampleDescription { get; set; }
public virtual Project Project { get; set; }
}
}
Here are my two Controller Action Methods for the AddCodeSample:
//
// GET: /Project/AddCodeSample
public ActionResult AddCodeSample()
{
return View();
}
//
// POST: /Project/AddCodeSample
[HttpPost]
public ActionResult AddCodeSample(ProjectCodeSample projectcodesample)
{
projectcodesample.ProjectCodeSampleContent = projectcodesample.ProjectCodeSampleContent.TrimStart();
if (ModelState.IsValid)
{
db.ProjectCodeSamples.Add(projectcodesample);
db.SaveChanges();
return RedirectToAction("Details/" + projectcodesample.ProjectID);
}
else
{
return View(projectcodesample);
}
}
Here is my AddCodeSample View:
#model ProDevPortMVC3.ProjectCodeSample
#{
ViewBag.Title = "Add Code Sample";
}
<style type="text/css">
.editor-label { width: 200px; }
.editor-field { width: 700px; }
.submit-button-row { width: 900px; }
.bottom-nav { width: 900px; }
</style>
<h2>Add Code Sample</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 style="float: left; width: 900px;">
<legend>Project Code Sample</legend>
#Html.HiddenFor(model => model.ProjectID)
<div class="display-editor-label-field-row">
<div class="editor-label">
#Html.LabelFor(model => model.ProjectCodeSampleDescription, "Code Sample Description")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.ProjectCodeSampleDescription, 4, 85, null)
#Html.ValidationMessageFor(model => model.ProjectCodeSampleDescription)
</div>
</div>
<br />
<div class="display-editor-label-field-row">
<div class="editor-label">
#Html.LabelFor(model => model.ProjectCodeSampleContent, "Code Sample")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.ProjectCodeSampleContent, 15, 85, null)
#Html.ValidationMessageFor(model => model.ProjectCodeSampleContent)
</div>
</div>
<br />
<div class="display-editor-label-field-row">
<div class="submit-button-row">
<input type="submit" value="Save" />
</div>
</div>
<br />
<div class="bottom-nav">
#Html.ActionLink("Cancel", "Details", new { id = ViewContext.RouteData.Values["ID"] })
</div>
</fieldset>
}
So obviously this will not work, because "#Html.HiddenFor(model => model.ProjectID)" will be empty... So what am I doing wrong, how do you get the Parent ID so that you can make Child entries?

You could pass the id from the previous page into this page using a querystring in your link:
public ActionResult AddCodeSample(int id)
{
var m = new ProjectCodeSample();
m.ProjectID = id;
return View(m);
}
So on your 'parent' project page, it could have a link like this:
Add Code Sample

Related

Why are my required attributes of my model not work in MVC3

In my class file where my model is I have required attributes such as:
[Required]
[Range(0, 99, ErrorMessage = "Sorry, you must select a range between 0 - 99.")]
public int MaxConcurrentUsers { get; set; }
So you would think that when I click the submit button on the page to post the values, that because I have typed an incorrect value for MaxConcurrentUsers it wouldn't reach the actionResult method in my C# code. But it does. One thing I have noticed is that my modelstate .valid is false, but I want the client to stop it from getting to that method. What am I doing wrong?
My model
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace UserManager.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class vw_UserManager_Model
{
public string rowtype { get; set; }
public System.Guid applicationid { get; set; }
public System.Guid userid { get; set; }
// [StringLength(12, MinimumLength = 6,
//ErrorMessage = "Username must be between 6 and 12 characters.")]
public string UserName { get; set; }
[Required]
[Range(0, 99, ErrorMessage = "Sorry, you must select a range between 0 - 99.")]
public int MaxConcurrentUsers { get; set; }
[Required(ErrorMessage = "First name is a required field")]
[Display(Name = "First name")]
public string firstname { get; set; }
[Required(ErrorMessage = "Last name is a required field")]
[Display(Name = "Last name")]
public string lastname { get; set; }
public string salutation { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string password { get; set; }
[Required(ErrorMessage = "Email is required.")]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string email { get; set; }
public string group_name { get; set; }
public Nullable<long> group_id { get; set; }
public int moduleid { get; set; }
public Nullable<int> session_status { get; set; }
public Nullable<int> islockedout { get; set; }
public Nullable<bool> isactive { get; set; }
public bool IsApproved { get; set; }
public bool alf { get; set; }
public bool brad { get; set; }
public string module_name { get; set; }
public string CompanyName { get; set; }
public string CompanySearch { get; set; }
public string selected_module { get; set; }
public string selected_group { get; set; }
public string selected_moduleAlf { get; set; }
public string selected_moduleBrad { get; set; }
public string selected_groupAlf { get; set; }
public string selected_groupBrad { get; set; }
}
}
My view
#model UserManager.Models.vw_UserManager_Model
<h2 style="padding-left: 25px;">
Create user</h2>
#using (Html.BeginForm())
{
<!-- ALF/BRAD selection -->
#Html.ValidationSummary(true)
<fieldset style="width: 400px; padding-left: 15px;">
<legend>Select module type:</legend>
<div class="module-selection">
#Html.Label("Select ALF")
<input type="checkbox" checked="checked" id="chkAlf" name="selection" value="Alf"
onclick="chkSelection()" />
#Html.Label("Select BRAD")
<input type="checkbox" id="chkBrad" name="selection" value="Brad" onclick="chkSelection()" />
</div>
</fieldset>
<!-- Module selection -->
<fieldset style="width: 400px; padding-left: 15px;">
<legend>Select module:</legend>
<div id="alfModules">
#{Html.RenderAction("_CreateUserModulesAlf", "UserManager");}
</div>
<br />
<div id="bradModules">
#{Html.RenderAction("_CreateUserModulesBrad", "UserManager");}
</div>
</fieldset>
<!-- Check if group exists -->
<fieldset style="width: 400px; padding-left: 15px;">
<legend>Group Checker</legend>
<div id="createuser-groupnamesearch">
#{Html.RenderAction("_txtGroupSearchForm", "UserManager");}
</div>
</fieldset>
<fieldset style="width: 400px; padding-left: 15px;">
<legend>New User Details</legend>
<div class="editor-label">
#Html.LabelFor(Model => Model.salutation)
</div>
<div class="editor-field">
#Html.DropDownListFor(Model => Model.salutation, new List<SelectListItem>
{
new SelectListItem{ Text="Mr", Value = "Mr" },
new SelectListItem{ Text="Mrs", Value = "Mrs" },
new SelectListItem{ Text="Miss", Value = "Miss" },
new SelectListItem{ Text="Ms", Value = "Ms" },
new SelectListItem{ Text="Dr", Value = "Dr" }
})
#Html.ValidationMessageFor(model => Model.salutation)
</div>
<div id="createuser-usernamesearch">
#{Html.RenderAction("_txtUsernameSearch", "UserManager");}
</div>
<div class="editor-label">
#Html.Label("Firstname")
</div>
<div class="editor-field">
#Html.EditorFor(model => Model.firstname)
#Html.ValidationMessageFor(model => Model.firstname)
</div>
<div class="editor-label">
#Html.Label("Surname")
</div>
<div class="editor-field">
#Html.EditorFor(model => Model.lastname)
#Html.ValidationMessageFor(model => Model.lastname)
</div>
<div class="editor-label">
#Html.Label("Password")
</div>
<div class="editor-field">
#Html.EditorFor(model => Model.password)
#Html.ValidationMessageFor(model => Model.password)
</div>
<div class="editor-label">
#Html.Label("Email")
</div>
<div class="editor-field">
#Html.EditorFor(model => Model.email)
#Html.ValidationMessageFor(model => Model.email)
</div>
<div class="editor-label">
#Html.Label("Is active")
</div>
<div class="editor-field">
#Html.EditorFor(model => Model.isactive)
#Html.ValidationMessageFor(model => Model.isactive)
</div>
<div class="editor-label">
#Html.Label("Maximum concurrent users")
</div>
<div class="editor-field">
#Html.EditorFor(model => Model.MaxConcurrentUsers)
#Html.ValidationMessageFor(model => Model.MaxConcurrentUsers, "Enter a number between 0-99.")
</div>
<div id="moduleSelection">
#Html.HiddenFor(Model => Model.selected_moduleAlf, new { id = "hdnModuleAlf" })
#Html.HiddenFor(Model => Model.selected_moduleBrad, new { id = "hdnModuleBrad" })
</div>
<input type="submit" value="Create" onclick="return submitWith();" />
<span id="validationMessage"></span>
<br />
<br />
#Html.ActionLink("Back to List", "Index")
</fieldset>
<div>
#Html.ValidationSummary()
</div>
}
<script type="text/javascript">
// Count checkboxes that are checked.
function submitWith() {
var checkedCount = $("input:checked").length;
var valid = checkedCount > 0;
// Check that one checkbox is checked first
if (!valid) { // IF false
$('#validationMessage').html('You must select at least one option').css("background-color", "red");
}
// Second check ALF
else if ($('.module-selection #chkAlf').is(':checked')) {
if ($("#txtGroupnameExistsAlf").val() == "Alf Group doesn't exist.") {
valid = false;
$('#validationMessage').html('Group must exist in ALF Database first').css("background-color", "red");
}
if ($("#txtGroupnameExistsAlf").val() == "") {
valid = false;
$('#validationMessage').html('A group must be picked when creating a new user.').css("background-color", "red");
}
}
// Third check
else if ($('.module-selection #chkBrad').is(':checked')) {
if ($("#txtGroupnameExistsBrad").val() == "Brad Group doesn't exist.") {
valid = false;
$('#validationMessage').html('Group must exist in BRAD Database first').css("background-color", "red");
}
if ($("#txtGroupnameExistsBrad").val() == "") {
valid = false;
$('#validationMessage').html('A group must be picked when creating a new user.').css("background-color", "red");
}
}
else {
valid = true;
}
return valid;
}
function chkSelection() {
// alert("check selection");
filters = new Object();
if ($('.module-selection #chkAlf').is(':checked')) {
// Show Div
$("#alfModules").show();
$("#groupname-checker-alf").show();
// Show username checker for Alf
$("#username-checker-alf").show();
// Set ALF model property to true
$("#hdnAlf").val("true");
// Set alf value for one to be passed to Ajax request
filters.alf = 1;
var selectedVal = $("#ddlSelectedAlf :selected").val();
$('#hdnModuleAlf').val(selectedVal);
}
else {
$("#alfModules").hide();
$("#groupname-checker-alf").hide();
$("#hdnAlf").val("false");
$("#username-checker-alf").hide();
filters.alf = 0;
$('#hdnModuleAlf').val("false");
$("#txtGroupnameExistsAlf").val("").css("background-color", "white");
}
if ($('.module-selection #chkBrad').is(':checked')) {
// Show Div
$("#bradModules").show();
$("#groupname-checker-brad").show();
// Show username checker for Alf
$("#username-checker-brad").show();
// Set alf value for one to be passed to Ajax request
filters.brad = 1;
var selectedVal = $("#ddlSelectedBrad :selected").val();
$('#hdnModuleBrad').val(selectedVal);
}
else {
$("#bradModules").hide();
$("#groupname-checker-brad").hide();
$("#hdnBrad").val("false");
$("#username-checker-brad").hide();
filters.brad = 0;
$('#hdnModuleBrad').val("false");
$("#txtGroupnameExistsBrad").val("").css("background-color", "white");
}
filters.username = $('#createuser-usernamesearch #user_name').val();
return filters;
}
function searchUsername() {
var filters = chkSelection();
$.ajax({
url: '#Url.Action("UsernameSearch", "UserManager")',
type: "POST",
async: true,
dataType: "json",
data: "username=" + filters.username,
success: function (data) {
var usernameExistsAlf = parseInt(data.usernameAlf);
if (usernameExistsAlf > 0) {
$('#txtUsernameExistsAlf').val("Username already exists").css("background-color", "red");
}
else {
$('#txtUsernameExistsAlf').val("Username doesn't exist").css("background-color", "#33ff00");
}
var usernameExistsBrad = parseInt(data.usernameBrad);
if (usernameExistsBrad > 0) {
$('#txtUsernameExistsBrad').val("Username already exists").css("background-color", "red");
}
else {
$('#txtUsernameExistsBrad').val("Username doesn't exist").css("background-color", "#33ff00");
}
},
error: function (data) {
}
});
}
$("#group_name").autocomplete({
source: function (request, response) {
$.ajax({
url: '#Url.Action("LookUpGroupName", "UserManager")',
dataType: "json",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
value: request.term
},
success: function (data) {
response($.map(data, function (item) {
// alert(item.group);
return {
label: item.group,
value: item.group
} // end of return
})); // end of response
}, // end of success
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus);
} // end of error
}); // end of ajax
},
minLength: 2,
select: function (event, ui) { // Assign to hidden values to trigger onchange ajax call.
$.ajax({
url: '#Url.Action("GroupnameCheck", "UserManager")',
dataType: "json",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
value: ui.item.label
},
success: function (data) {
$.each(data, function (index, value) {
if (index == "AlfGroup") {
$("#txtGroupnameExistsAlf").val(value);
if ($("#txtGroupnameExistsAlf").val() == "Alf Group doesn't exist.") {
$("#txtGroupnameExistsAlf").css("background-color", "red");
}
else {
$('#txtGroupnameExistsAlf').css("background-color", "#33ff00");
}
}
if (index == "BradGroup") {
$("#txtGroupnameExistsBrad").val(value);
if ($("#txtGroupnameExistsBrad").val() == "Brad Group doesn't exist.") {
$("#txtGroupnameExistsBrad").css("background-color", "red");
}
else {
$('#txtGroupnameExistsBrad').css("background-color", "#33ff00");
}
}
});
}, // end of success
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus);
} // end of error
}); // end of ajax
$('#hdnGroupAlf').val(ui.item.label);
$('#hdnGroupBrad').val(ui.item.label);
},
open: function () {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
$(document).ready(function () {
chkSelection();
});
</script>
My layout with all the scripts
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<!-- Javascript -->
<script src="../../Scripts/jquery-1.8.3.min.js" type="text/javascript"></script>
#* <script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>*#
<script src="#Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
#* <script src="#Url.Content("~/Scripts/jquery.autocomplete.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/Custom/autocompleteGroup.js")" type="text/javascript"></script>*#
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<!-- Javascript -->
<!-- Stylesheets -->
<link href="#Url.Content("~/Content/themes/base/jquery.ui.autocomplete.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/themes/base/jquery.ui.autocomplete.custom.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<!-- Stylesheets -->
</head>
<body>
<div class="page">
<div id="header">
<div id="title" >
<h1>ALF and BRAD User Manager</h1>
</div>
<div id="logindisplay">
<span style="color:Black; background-color:white; text-align:right;">
Logged in as:&nbsp<strong>#Context.User.Identity.Name</strong>
</span>
</div>
<nav>
<ul id="menu">
#Html.ActionLink("User Manager Dashboard", "Index", "UserManager")&nbsp&nbsp
#Html.ActionLink("User Analytics", "Index", "UserStatus")&nbsp&nbsp
#Html.ActionLink("Email Distibution", "Index", "EmailDistributionList")&nbsp&nbsp
#Html.ActionLink("Email User Details", "Index", "EmailUserDetails")&nbsp&nbsp
</ul>
</nav>
</div>
<section id="main">
#RenderBody()
</section>
<footer>
</footer>
</div>
</body>
</html>
#* <script type="text/javascript">
$(document).ready(function () {
doAutocomplete('#Url.Action("LookUpGroupName", "UserManager")');
});
</script>*#
So any help? Thanks!
This is how it should work. You will still get to the method, but can check the ModelState to decide what to do, for example...
if (ModelState.IsValid) {
// Save, redirect to action
}
return View(model); // send them back to correct the problem!
You will also be able to display the errors on the view, as they will be present. You can use a ValidationSummary or have individual ValidationFor elements.
Check the below link. It may help you.
Client side validation
Update:
You need to enable clientside validation, unobtrusivejavascript and refer the script files in master page.
[web.config]
<appSettings>
<add key="webpages:Version" value="1.0.0.0" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
[layout.cshtml]
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

ASP.NET MVC 3 Model has no information on postback

I have a view with a couple of partial views that I bind to my model. For some reason, when I post, the model is empty, and I am not sure why.
Below is my ViewModel.
public class IndexViewModel
{
public bool AdvancedSearchOption { get; set; }
public bool ForceAdvanced { get; set; }
public bool ForceSimple { get; set; }
public string SimpleSearchCriteria { get; set; }
public string CustomerNumberCriteria { get; set; }
public string AccountNumberCriteria { get; set; }
public string NameCriteria { get; set; }
public string PhoneNumberCriteria { get; set; }
}
Here is my controller. I am filling in all the values of the viewmodel because I wanted to see if the values got to the partial views. They do get there, so it is just on the post that I am having issues.
public class HomeController : Controller
{
private ISecurityRepository SecurityRep;
public HomeController(ISecurityRepository repo)
{
SecurityRep = repo;
}
public ActionResult Index()
{
IndexViewModel temp = new IndexViewModel();
temp.AdvancedSearchOption = SecurityRep.DefaultToAdvancedSearch(User.Identity.Name);
temp.ForceAdvanced = false;
temp.ForceSimple = false;
temp.SimpleSearchCriteria = "Testing";
temp.AccountNumberCriteria = "Acct";
temp.CustomerNumberCriteria = "Cust";
temp.NameCriteria = "Name";
temp.PhoneNumberCriteria = "Phone";
return View(temp);
}
public ActionResult SimpleSearch()
{
IndexViewModel temp = new IndexViewModel();
temp.AdvancedSearchOption = SecurityRep.DefaultToAdvancedSearch(User.Identity.Name);
temp.ForceAdvanced = false;
temp.ForceSimple = true;
temp.SimpleSearchCriteria = "Testing";
temp.AccountNumberCriteria = "Acct";
temp.CustomerNumberCriteria = "Cust";
temp.NameCriteria = "Name";
temp.PhoneNumberCriteria = "Phone";
return View("Index",temp);
}
public ActionResult AdvancedSearch()
{
IndexViewModel temp = new IndexViewModel();
temp.AdvancedSearchOption = SecurityRep.DefaultToAdvancedSearch(User.Identity.Name);
temp.ForceAdvanced = true;
temp.ForceSimple = false;
temp.SimpleSearchCriteria = "Testing";
temp.AccountNumberCriteria= "Acct";
temp.CustomerNumberCriteria= "Cust";
temp.NameCriteria= "Name";
temp.PhoneNumberCriteria = "Phone";
return View("Index", temp);
}
[HttpPost]
public ActionResult Index(IndexViewModel vm, FormCollection formCollection)
{
return View();
}
}
Here is my view
#model TRIOSoftware.Magnum.Models.IndexViewModel
#{
ViewBag.Title = "Search";
}
#if ((#Model.AdvancedSearchOption && #Model.ForceSimple != true) || #Model.ForceAdvanced == true)
{
#Html.Partial("AdvancedSearch")
}
else
{
#Html.Partial("SimpleSearch")
}
Here is my SimpleSearch partial view. I think if I can get this one working, the other will follow the same path. I do the post in the partial and I use jQuery to do it. I am not sure if either of these things could cause me issues or not. I only have all the hidden items in there because I didn't know if not having them was causing my issues.
#model TRIOSoftware.Magnum.Models.IndexViewModel
<script type="text/javascript">
$(document).ready(function () {
$("#DefaultDiv").find("#DefaultAdvanced").click(function () {
$.post("DefaultSimple");
});
$("#SearchSection").find("#SearchButton").click(function () {
$.post("");
});
});
</script>
#using (Html.BeginForm("Index","Home"))
{
#Html.HiddenFor(m => m.ForceAdvanced)
#Html.HiddenFor(m => m.AdvancedSearchOption)
#Html.HiddenFor(m => m.ForceSimple)
#Html.HiddenFor(m => m.AccountNumberCriteria)
#Html.HiddenFor(m => m.CustomerNumberCriteria)
#Html.HiddenFor(m => m.NameCriteria)
#Html.HiddenFor(m => m.PhoneNumberCriteria)
<div id="DefaultDiv" style="float:right">
<a id="DefaultAdvanced" href="#" class="ButtonClass">Default Simple Search</a>
</div>
<div style="clear:both; margin: auto; width: 800px">
<img src="../../Content/images/TRIO_transparent_image.gif"; alt="TRIO Software"; style="margin-left:150px; clear:left"/>
<div style="clear:left; float: left" class="SearchText">
#Html.Label("What's your inquiry?:")
#Html.EditorFor(m => m.SimpleSearchCriteria, new { style = "width: 400px" })
</div>
<div id="SearchSection" style="float: left" class="SearchText">
<img src="../../Content/images/Search.gif"; alt="Search"; style="float:left" />
</div>
<p style="clear:left;margin-left:400px">
#Html.ActionLink("Advanced Search", "AdvancedSearch", null, new { style = "clear:left" })
</p>
</div>
}
Here is the HTML code when viewing the simple search partial view:
<div id="main">
<script type="text/javascript">
$(document).ready(function () {
$("#DefaultDiv").find("#DefaultAdvanced").click(function () {
$.post("DefaultSimple");
});
$("#SearchSection").find("#SearchButton").click(function () {
$.post("");
});
});
</script>
<form method="post" action="/">
<input type="hidden" value="False" name="ForceAdvanced" id="ForceAdvanced" data-val-required="The ForceAdvanced field is required." data-val="true">
<input type="hidden" value="False" name="AdvancedSearchOption" id="AdvancedSearchOption" data-val-required="The AdvancedSearchOption field is required." data-val="true">
<input type="hidden" value="False" name="ForceSimple" id="ForceSimple" data-val-required="The ForceSimple field is required." data-val="true">
<input type="hidden" value="Acct" name="AccountNumberCriteria" id="AccountNumberCriteria">
<input type="hidden" value="Cust" name="CustomerNumberCriteria" id="CustomerNumberCriteria">
<input type="hidden" value="Name" name="NameCriteria" id="NameCriteria">
<input type="hidden" value="Phone" name="PhoneNumberCriteria" id="PhoneNumberCriteria">
<div style="float:right" id="DefaultDiv">
<a class="ButtonClass ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" href="#" id="DefaultAdvanced" role="button"><span class="ui-button-text">Default Simple Search</span></a>
</div>
<div style="clear:both; margin: auto; width: 800px">
<img style="margin-left:150px; clear:left" alt="TRIO Software" ;="" src="../../Content/images/TRIO_transparent_image.gif">
<div class="SearchText" style="clear:left; float: left">
<label for="What_s_your_inquiry_:">What's your inquiry?:</label>
<input type="text" value="Testing" name="SimpleSearchCriteria" id="SimpleSearchCriteria" class="text-box single-line">
</div>
<div class="SearchText" style="float: left" id="SearchSection">
<a class="ButtonClass ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" id="SearchButton" ;="" href="#" role="button"><span class="ui-button-text"><img style="float:left" alt="Search" ;="" src="../../Content/images/Search.gif"></span></a>
</div>
<p style="clear:left;margin-left:400px">
<a style="clear:left" href="/Home/AdvancedSearch">Advanced Search</a>
</p>
</div>
</form>
</div>
How do I fix this problem?
Although you're selecting a partial to render, you're not passing it the model. There's an overloaded version of Html.Partial that takes a second argument that allows you to pass a model to it:
#Html.Partial("ViewName", Model);
So in your case, you'd use this:
#if ((Model.AdvancedSearchOption && Model.ForceSimple != true) || Model.ForceAdvanced == true)
{
#Html.Partial("AdvancedSearch", Model)
}
else
{
#Html.Partial("SimpleSearch", Model)
}
Also notice how I've removed the #s you were prefixing Model with. To better understand why, please see Introduction to ASP.NET Web Programming Using the Razor Syntax and a small reference for this same topic written by Phil Haack here.
I think #john-h hit the nail on the head with his answer. However, you might want to reduce the complexity you've created for yourself.
1) Since both ForceSimple and ForceAdvanced are Boolean, it would be assumed that when ForceAdvanced is true, then it's not "Simple", right? I'm not sure what other logic you have here.
2) Rather than creating two views and "posting" back to get the correct one, why not just use a parameter to set the search type? Or evaluate the security to set which one the user can execute. Here's an example:
Controller Actions:
//id is the search type: true is Advanced
public ActionResult Search(bool id) {
IndexViewModel viewModel = new IndexViewModel {
/* Do whatever logic here */
ForceAdvanced = (id) ? false : true,
AdvancedSearchOption = id
};
return View("search", viewModel);
}
[HttpPost]
public ActionResult Search(IndexViewModel model) {
//model.SimpleSearchCriteria = "Testing";
//model.PhoneNumberCriteria = "Phone";
return View("search", model);
}
Search View:
#using (#Html.BeginForm(new { id = #Model.AdvancedSearchOption })) {
<div style="clear:left; float: left" class="SearchText">
#Html.Label("What's your inquiry?:")
#if (Model.AdvancedSearchOption) {
<div>
#* if you really want, load your partial views here *#
<span>#Html.LabelFor(m => m.NameCriteria)</span>
#Html.EditorFor(m => m.NameCriteria, new { style = "width: 400px" })
<span>#Html.LabelFor(m => m.PhoneNumberCriteria)</span>
#Html.EditorFor(m => m.PhoneNumberCriteria, new { style = "width: 400px" })
</div>
}
else {
#* if you really want, load your partial views here *#
#Html.EditorFor(m => m.SimpleSearchCriteria, new { style = "width: 400px" })
}
</div>
<div>
<input type="submit" value="Search" />
</div>
#Html.HiddenFor(m => m.ForceAdvanced)
#Html.HiddenFor(m => m.AdvancedSearchOption)
#Html.HiddenFor(m => m.ForceSimple)
#Html.HiddenFor(m => m.AccountNumberCriteria)
#Html.HiddenFor(m => m.CustomerNumberCriteria)
#Html.HiddenFor(m => m.NameCriteria)
#Html.HiddenFor(m => m.PhoneNumberCriteria)
}
I had tried explicitly sending in the model to the partials with no luck. I believe that the partial views get the parent model by default if nothing is specified, so all I needed to do was to specify the model type in my partials, and I got the information.
I finally figured it out with a lot of trial and error. My issue was being caused by me trying to use jQuery to do a post. There must be some other things you need to do to update your model doing it this way. Once I changed it out and put an input control on the form for the post, I got all my data back from the parent and partial view in the controller.

html.dropdownlist MVC3 confusion

This works for me but how do I do the same thing using html.dropdownlist?
Notice that the value passed is not the value that is shown to the user.
#model IEnumerable<MVR.Models.ViewIndividual>
<h2>Level1</h2>
<select>
#foreach (var item in Model) {
<option value="#item.Case_Number">#item.Patient_Lastname ,
#item.Patient_Firstname
</option>
}
</select>
As always in an ASP.NET MVC application you start by defining a view model:
public class MyViewModel
{
public string SelectedIndividual { get; set; }
public SelectList Individuals { get; set; }
}
then you write a controller action that populates this view model from some data source or something:
public ActionResult Index()
{
// TODO : fetch those from your repository
var values = new[]
{
new { Value = "1", Text = "item 1" },
new { Value = "2", Text = "item 2" },
new { Value = "3", Text = "item 3" },
};
var model = new MyViewModel
{
Individuals = new SelectList(values, "Value", "Text")
};
return View(model);
}
and finally you have a strongly typed view using strongly typed helpers:
#model MyViewModel
#Html.DropDownListFor(
x => x.SelectedIndividual,
Model.Individuals
)
This being said, because I see that you are not using any view models in your application, you could always try the following ugliness (not recommended, do this at your own risk):
#model IEnumerable<MVR.Models.ViewIndividual>
<h2>Level1</h2>
#Html.DropDownList(
"SelectedIndividual",
new SelectList(
Model.Select(
x => new {
Value = x.Case_Number,
Text = string.Format(
"{0}, {1}",
x.Patient_Lastname,
x.Patient_Firstname
)
}
),
"Value",
"Text"
)
)
Of course such pornography is not something that I would recommend to ever write in a view and I wouldn't recommend even to my worst enemies.
Conclusion: In an ASP.NET MVC application you should always be using view models and strongly typed views with strongly typed helpers (see first part of my answer).
Here is the full example
public class PageModel
{
[Display(Name = "Page ID")]
public Guid ID { get; set; }
[Display(Name = "Page Type ID")]
public Guid PageTypeID { get; set; }
[Display(Name = "Title")]
public string Title { get; set; }
[Display(Name = "Page Type Name")]
public string PageTypeName { get; set; }
[Display(Name = "Html Content")]
public string HtmlContent { get; set; }
public SelectList PageTypeList { get; set; }
}
the C# code
public ActionResult Edit(Guid id)
{
var model = db.Pages.Where(p => p.ID == id).FirstOrDefault();
var typeList = new SelectList(db.PageTypes.OrderBy(s => s.Name).ToList(), "ID", "Name");
var viewModel = new PageModel { PageTypeList = typeList };
viewModel.HtmlContent = model.HtmlContent;
viewModel.ID = model.ID;
viewModel.PageTypeID = Guid.Parse(model.PageTypeID.ToString());
viewModel.Title = model.Title;
return View(viewModel);
}
[HttpPost]
[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(PageModel page)
{
if (ModelState.IsValid)
{
var model = db.Pages.Where(p => p.ID == page.ID).FirstOrDefault();
model.Title = page.Title;
model.HtmlContent = page.HtmlContent;
model.PageTypeID = page.PageTypeID;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(page);
}
and lastly html
#model competestreet.com.Models.PageModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_LayoutCMS.cshtml";
}
<script type="text/javascript">
$(document).ready(function () {
$('#HtmlContent').ckeditor();
});
</script>
<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>
<script src="#Url.Content("~/Scripts/ckeditor/ckeditor.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/ckeditor/adapters/jquery.js")" type="text/javascript"></script>
<h2 class="title">
<span class="text-cms">CM<span>S</span></span></h2>
<div class="box">
<div class="t">
</div>
<div class="c">
<div class="content">
<div class="main-holder">
<div id="sidebar">
<ul>
<li>Home</li>
<li>Pages</li>
</ul>
</div>
<div id="content" style="min-height: 500px;">
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Page Type - #Html.DropDownListFor(x => x.PageTypeID, Model.PageTypeList)
#Html.ValidationMessageFor(model => model.PageTypeID)</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title, new { #class = "text-box" })
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="clear">
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HtmlContent)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.HtmlContent, new { #name = "Editor1", #class = "Editor1" })
#Html.ValidationMessageFor(model => model.HtmlContent)
</div>
<div class="clear">
</div>
<p>
<input type="submit" value="Save" class="input-btn" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
</div>
</div>
<div class="b">
</div>
</div>

jQuery UI Datepicker not Posting to Server after Deployment

So I published a ASP.Net MVC3 project that uses the jQuery UI datepickers on to a IIS server. The datepickers don't seem to post their values and revert to default values on the back end.
Locally, though it works like a charm. It's simple jQuery without any options on the datepicker.
Any clue as to why that would happen?
Let me know what I can post to help find a solution.
Thanks!
The model I am trying to post back:
public class Report
{
[Required]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime From { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime To { get; set; }
public virtual Car Car { get; set; }
public virtual IEnumerable<Review> Reviews { get; set; }
}
The form I am using:
#model Cars.Models.Report
<h3>Create a report</h3>
#using (Html.BeginForm("Generate", "Report"))
{
<div>
<div class="span-5">
<div class="editor-label">
#Html.LabelFor(model => model.From)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.From, new { #class = "datepicker lilbig" })
</div>
</div>
<div class="span-5 last">
<div class="editor-label">
#Html.LabelFor(model => model.To)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.To, new { #class = "datepicker lilbig" })
</div>
</div>
<div class="span-11 last">
<div class="prepend-5 last">
<input class="bigbtn" type="submit" value="Create" />
</div>
<div>
#Html.ValidationSummary(true)
#Html.ValidationMessageFor(model => model.From)
#Html.ValidationMessageFor(model => model.To)
</div>
</div>
</div>
}
Method I am posting to:
[HttpPost]
public ActionResult Generate(Report model)
{
try
{
MembershipUser currentUser = Membership.GetUser(HttpContext.User.Identity.Name);
Guid id = (Guid)currentUser.ProviderUserKey;
Car currentCar = CarRepository.Get(id);
currentCar.LastReportCreated = DateTime.Now;
currentCar = CarRepository.Update(currentCar, true);
model.Car = currentCar;
model.Reviews = model.Car.Reviews.Where(s => s.LoggedAt.Date >= model.From.Date &&
s.LoggedAt.Date <= model.To.Date);
return View("Report", model);
}
catch(Exception ex)
{
return View("Error");
}
}
The jQuery looks like this:
$(document).ready(function () {
$(".datepicker").datepicker();
});
Check that the datepicker version on the server is current and running bug-free. Also double check your form data before it gets posted - make sure the date fields have values:
$(document).ready(function () {
$("form").submit(function(){
$(".datepicker").each(function(){
alert( $(this).attr("name") +": "+ $(this).value() );
});
});
});

mvc3 razor dropdownlistfor causing update model to fail

I have a problem with the following code. Basically when I call updatemodel it fails but I dont get an inner exception. If i change the drop down to a text box it works.
class:
public class Member
{
[Key]
public int MemberID { get; set; }
[StringLength(50),Required()]
public string Name { get; set; }
[Range(0,120)]
public short Age { get; set; }
[Required(),MaxLength(1)]
public string Gender {get; set;}
[Required()]
public virtual Team Team { get; set; }
}
controller methods:
[HttpGet]
public ActionResult ViewMember(int id)
{
try
{
var m = db.GetMember(id);
var maleItem = new SelectListItem{Text = "Male", Value= "M", Selected=m.Gender == "M"};
var femaleItem = new SelectListItem{Text = "Female", Value="F", Selected=m.Gender == "F"};
List<SelectListItem> items = new List<SelectListItem>();
items.Add(maleItem);
items.Add(femaleItem);
var genders = new SelectList(items, "Value", "Text");
ViewBag.Genders = genders;
return View(m);
}
catch (Exception ex)
{
return View();
}
}
[HttpPost]
public ActionResult ViewMember(Member m)
{
try
{
var member = db.GetMember(m.MemberID);
m.Team = db.GetTeam(member.Team.TeamID);
UpdateModel(member);
db.Save();
return RedirectToAction("ViewMembers", new { id = member.Team.TeamID });
}
catch (Exception ex)
{
return View();
}
}
and finally cshtml code:
#model GreenpowerAdmin.Models.Member
#using GreenpowerAdmin.Helpers
#{
ViewBag.Title = "ViewMember";
}
<h2>ViewMember</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>Member</legend>
#Html.HiddenFor(model => model.MemberID)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Team.Name)
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.Team.Name)
#Html.ValidationMessageFor(model => model.Team.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Age)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Age)
#Html.ValidationMessageFor(model => model.Age)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Gender)
</div>
<div class="editor-field">
#Html.DropDownList("Gender", ViewBag.Genders as SelectList)
#Html.ValidationMessageFor(model => model.Gender)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "ViewMembers", new { id=Model.Team.TeamID })
</div>
When I click the save button the updatemodel line fails. As said above, it doesn't fail if I use a text box for gender. Does anyone know what is making it fail or how to debug it?
Try declaring the MemberID property as a nullable integer:
[Key]
public int? MemberID { get; set; }

Resources