My model is this a Movie class with this metadata:
[MetadataType(typeof(MovieMetadata))]
public partial class Movie
{
}
class MovieMetadata
{
[ScaffoldColumn(false)]
public int id { get; set; }
[Required(ErrorMessage = "Title is required")]]
[StringLength(70, ErrorMessage = "Title must have a lenght less than 70")]
public string title { get; set; }
[Required(ErrorMessage = "The realese date of the movie is required")]
public DateTime releaseDate { get; set; }
public string storyline { get; set; }
public Binary poster { get; set; }
[ScaffoldColumn(false)]
public Binary trailer { get; set; }
}
My Create View has this code inside:
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "createForm", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="gallMemberBox">
<div class="rightFormContent">
<div>
#Html.LabelFor(model => model.title)
#Html.EditorFor(model => model.title)
#Html.ValidationMessageFor(model => model.title)
</div>
<div>
#Html.LabelFor(model => model.releaseDate)
#Html.EditorFor(model => model.releaseDate)
#Html.ValidationMessageFor(model => model.releaseDate)
</div>
<div>
#Html.Label("Poster")
<input name="poster" value="C:" id="poster" type="file" />
</div>
<div>
#Html.Label("Trailer")
#* #Html.TextBox("trailer", "", new { type = "file", id="trailer" })*#
<input name="trailer" value="" id="trailer" type="file" />
</div>
<div>
#Html.LabelFor(model => model.storyline)
#Html.TextAreaFor(model => model.storyline, new{id="storyline"})
</div>
<div>
#Html.Label("Directors")
<select class="chosen-select" multiple="" data-placeholder="Select directors">
#for(int i = 0; i < directors.Count; i ++)
{
<option value="#i">#directors[i].name</option>
}
</select>
</div>
<div>
#Html.Label("Actors")
<select class="chosen-select" multiple="" data-placeholder="Select actors of the Screen">
#for(int i = 0; i < actors.Count; i ++)
{
<option value="#i">#actors[i].name</option>
}
</select>
</div>
<div>
#Html.Label("Writers")
<select class="chosen-select" multiple="" data-placeholder="Select writers of the Film">
#for(int i = 0; i < writers.Count; i ++)
{
<option value="#i">#writers[i].name</option>
}
</select>
</div>
<input type="submit" value="Create" />
</div>
}
I just filled title and releaseDate and click on submit(Create), after that in my ModelState I have three parameters, title, releaseDate and storyline(I never put some value on this one, and the value is an empty string. On the others fields I never put a value and they do not come with that POST. Why? And how to fix this?
public ActionResult Create([Bind(Exclude = "poster, trailer")]Movie movie, HttpPostedFileBase poster, HttpPostedFileBase trailer)
{
Your field storyline will already be available by the id and name "storyline as this is created like by MVC.
Remove the "id" part, or use "#id = ...".
You can write:
<div>
Storyline
#Html.TextAreaFor(model => model.storyline)
</div>
Related
Net Core and have run into a speed bump. I desire to get the selected value of a #Html.DropDownListFor and pass the string value to a switch to continue to display the rest of my form.
I seen numerous ways to #onchange on stack but no way to pass the variable's data to a #switch
Model
public class RegisterViewModel
{
public int ID { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
// New guild yes or no
[Required]
[Display(Name = "Are you registering a NEW GUILD?")]
public string RegisterNewGuild { get; set; }
// If yes
[Display(Name ="Are you the Guild Leader of the guild your are trying to register?")]
public string GuildLeader { get; set; }
//if yes
[Display(Name = "As the Guild Leader, What is your character's name?")]
public string GuildLeaderName { get; set; }
// if NOT THE guild leader and register new guild was marked yes.
[Display(Name = "As the Guild Member who is registering your guild, what is your Guild Leader's character name?")]
public string GuildLeaderNameViaMember { get; set; }
// get the persons character name who is registering
[Display(Name = "What is your character's name?")]
public string MemberName { get; set; }
[Display(Name = " What is your Guild's name?")]
public string GuildName { get; set; }
}
public enum GuildLeaderEnum
{
Yes,
No
}
public enum RegisterNewGuildEnum
{
Yes,
No
}
public enum GuildNameEnum
{
Test1,
Test2
}
View
#model RegisterViewModel
#{
ViewData["Title"] = "Register";
}
<h2>#ViewData["Title"].</h2>
<form asp-controller="Account" asp-action="Register" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post" class="form-horizontal">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Password" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
</div>
<div id="RegisterNewGuild" class="form-group">
<label asp-for="RegisterNewGuild" class="col-md-2 control-label"></label>
<div class="col-md-offset-2 col-md-10">
#Html.DropDownListFor(m => m.RegisterNewGuild,
new SelectList(Enum.GetValues(typeof(RegisterNewGuildEnum))),
"")
</div>
</div>
#switch ()// This is where i need help to Capture the string from the select list above)
{
case "Yes":
<div id="GuildLeader" class="form-group">
<label asp-for="GuildLeader" class="col-md-2 control-label"></label>
<div class="col-md-offset-2 col-md-10">
#Html.DropDownListFor(m => m.GuildLeader,
new SelectList(Enum.GetValues(typeof(GuildLeaderEnum))),
"")
</div>
</div>
switch ()// This is where i need help to Capture the string from the select list above)
{
case "Yes":
<div id="GuildLeaderName" class="form-group">
<label asp-for="GuildLeaderName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="GuildLeaderName" class="form-control" />
</div>
</div>
break;
case "No":
<div id="GuildLeaderNameViaMember" class="form-group">
<label asp-for="GuildLeaderNameViaMember" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="GuildLeaderNameViaMember" class="form-control" />
</div>
</div>
break;
}
break;
case "No":
<div id="MemberName" class="form-group">
<label asp-for="MemberName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="MemberName" class="form-control" />
</div>
</div>
<div id="GuildName" class="form-group">
<label asp-for="GuildName" class="col-md-2 control-label"></label>
<div class="col-md-10">
#Html.DropDownListFor(m => m.GuildName,
new SelectList(Enum.GetValues(typeof(GuildNameEnum))),
"")
</div>
</div>
break;
}
Controller
// GET: /Account/Register
[HttpGet]
[AllowAnonymous]
public IActionResult Register( string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null )
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link
//var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
//var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
//await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
// $"Please confirm your account by clicking this link: <a href='{callbackUrl}'>link</a>");
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(3, "User created a new account with password.");
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
This is my Model.
public class Territory
{
[Display(Name = "ID", ResourceType = typeof(Resources.Resource))]
public long ID { get; set; }
[Display(Name = "Name", ResourceType = typeof(Resources.Resource))]
public string Name { get; set; }
[Display(Name = "Code", ResourceType = typeof(Resources.Resource))]
public string Code { get; set; }
[Display(Name = "ProviderKey", ResourceType = typeof(Resources.Resource))]
public string ProviderKey { get; set; }
[Display(Name = "Provider", ResourceType = typeof(Resources.Resource))]
public string Provider { get; set; }
[Display(Name = "Countries", ResourceType = typeof(Resources.Resource))]
public virtual IList<Country> Countries { get; set; }
[Display(Name = "Rights", ResourceType = typeof(Resources.Resource))]
public IList<RightApplication> Rights { get; set; }
}
This is my Controller Edit action.
public ActionResult Edit(long id) {
var territory = new db.Territories.FindAsync(id);
if(territory == null) return HttpNotFound();
ViewBag.Countries = new SelectList(db.Countries.AsEnumerable(), "ID", "Name");
return View("Edit", territory);
}
And this is my Index view.
#foreach (var item in Model.Items)
{
<div class="col-lg-2 col-md-3 col-sm-3 col-xs-1">
<h4 class="pull-right" style="margin:4px;"><i class="fa fa-edit"></i>-<i class="fa fa-trash-o"></i></h4>
<div class="panel panel-success territory panel-scroll">
<div class="panel-heading">#item.Name</div>
<div class="panel-body">
<ul class="list-group">
#foreach (var country in item.Countries)
{
<li class="list-group-item">#country.Name</li>
}
</ul>
</div>
</div>
</div>
}
This is my Create View.
#using (Html.BeginForm(htmlAttributes: new { #class = "form single-col" }))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.Name)
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="form-group">
#Html.LabelFor(model => model.Code)
#Html.EditorFor(model => model.Code)
#Html.ValidationMessageFor(model => model.Code)
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProviderKey)
#Html.EditorFor(model => model.ProviderKey)
#Html.ValidationMessageFor(model => model.ProviderKey)
</div>
<div class="form-group">
#Html.LabelFor(model => model.Provider)
#Html.EditorFor(model => model.Provider)
#Html.ValidationMessageFor(model => model.Provider)
</div>
<div class="form-group">
#Html.LabelFor(model => model.Countries)
#Html.DropDownList("Countries")
</div>
<div class="form-group">
<div class="controls">
<div class="btn-group">
#if (Model.ID == 0)
{
<button type="submit" class="btn btn-primary"><i class="fa fa-plus"></i> Create</button>
}
else
{
<button type="submit" class="btn btn-primary"><i class="fa fa-pencil"></i> Update</button>
}
<a class="btn btn-info" href="#Url.Action("Index")"><i class="fa fa-arrow-left"></i> Back to List</a>
</div>
</div>
</div>
}
I'm trying Country select from DropdownList to show in Index view.I have get Territory Name in index view,but i'm not able to add Country Name in Territory.
there are 2 ways to save the data from the drop down. The first is a little more work and isn't as reliable. Look at the rendered drop down and if there isn't a name on it, add one
#Html.DropDownList("Countries", Model.CountriesList, new { name = "Country" })
with that on your controller you can get the selected value by
Request.Form["Country"].ToString();
the way I would recommend is to change your drop down to a for helper
#Html.DropDownListFor(x => x.Country, Model.CountriesList)
this will tie the selected value to your model (Country in this case) which you can then pull out in your post method
I'm having a little trouble passing url variables to a form on a separate view. Basically I have a 'HomeController' which has a 'Contact' action and view, and a 'SalesController' which has an action and a view called 'View'.
On the view called 'View' (confusing I know), I have an action link like so:
<a href="#Url.Action("Contact", "Home", new { pid = Model.Property[0].Pid, type = "Viewing"})" class="detailsBtn">
As you can see, this is passing two variables of 'pid' and 'type' to the 'Contact' action of the 'HomeController'. The contact returns a strongly typed view with the following model being used.
public class ContactModel
{
[Required]
[DataType(DataType.Text)]
public string FullName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string Email { get; set; }
[Required]
[DataType(DataType.PhoneNumber)]
[Phone(ErrorMessage = "Invalid Phone Number")]
public string Telephone { get; set; }
[DataType(DataType.Text)]
public string Address { get; set; }
[Required]
[DataType(DataType.Text)]
public string Subject { get; set; }
[Required]
[DataType(DataType.Text)]
public string Message { get; set; }
}}
Here's the Contact view:
#using (Html.BeginForm())
{
<div class="formField">
<span class="label">Full Name *</span><br />
#Html.TextBoxFor(Model => Model.FullName, new { #class = "txtContact" })
#Html.ValidationMessageFor(Model => Model.FullName, "Full enter your full name")<br/>
</div>
<div class="formField">
<span class="label">Email Address *</span><br />
#Html.TextBoxFor(Model => Model.Email, new { #class = "txtContact" })
#Html.ValidationMessageFor(Model => Model.Email, "Please ensure that a valid email is entered.")<br/>
</div>
<div class="formField">
<span class="label">Telephone *</span><br />
#Html.TextBoxFor(Model => Model.Telephone, new { #class = "txtContact" })
#Html.ValidationMessageFor(Model => Model.Telephone, "Please enter a valid telephone number")<br/>
</div>
<div class="formField">
<span class="label">Property Address (optional)</span><br />
#Html.TextBoxFor(Model => Model.Address, new {#class = "txtContact" })<br />
</div>
<div class="formField">
<span class="label">Subject *</span><br />
#if (ViewBag.Pid != null) {
#Html.TextBoxFor(Model => Model.Subject, new {#class = "txtContact" })
} else {
#Html.TextBoxFor(Model => Model.Subject, new { #class = "txtContact" })
}
#Html.ValidationMessageFor(Model => Model.Subject, "Please enter a subject")<br/>
</div>
<div class="formField">
<span class="label">Message *</span><br />
#Html.TextAreaFor(Model => Model.Message, new { #class = "txtContact" })
#Html.ValidationMessageFor(Model => Model.Message, "Please enter a message")<br/>
</div>
<input type="submit" class="contact-btn" value="Send" />
}
I simply need to know the best way for me to add the 'pid' and 'type' variables passed to the Contact Action from the Action link in the Sales Controller as values for my text boxes in the contact form.
You can always extend your Model to include a PID and Type property.
In your form you could just enter #Html.HiddenFor(Model => model.Pid) and #Html.HiddenFor(Model => model.Type) (or #Html.DisplayFor if you want them visible)
If you didn't want to do that, you could put your PID and Type values into ViewBag or ViewData from the Action, and then put these values into form fields in your view.
Edit:
If you would like the Pid and Type to be part of your strongly typed view, you can change your model to be like the following:
public class ContactModel
{
//all your other properties...
public string ContactType { get; set; }
public string Pid { get; set; }
}
Then in your Contact action, you can:
var model = new ContactModel() { ContactType = type, Pid = pid };
return View(model);
I have a question about using a dropdownlist in ASP.net MVC.
This is my situation:
Create view:
#using (Html.BeginForm("Create", "Deliverable", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>EventViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Thumbnail)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Thumbnail, new { type = "file" })
#Html.ValidationMessageFor(model => model.Thumbnail)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Image)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Image , new {type="file"})
#Html.ValidationMessageFor(model => model.Image)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.VideoUrl)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.VideoUrl)
#Html.ValidationMessageFor(model => model.VideoUrl)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.VideoUrl)
</div>
<div class="editor-field">
#Html.ValidationMessageFor(model => model.VideoUrl)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
After the 'VideoURL' I would like to have a Dropdownlist with values that are stored in my database. Most of the tutorials that I find don't bind the values in the dropdownlist to the database.
I insert the values in my db in my backoffice so I can't insert them in frontoffice...
This is my Controller:
public ActionResult Create(DeliverableViewModel model)
{
var afstudeerrichtingen = (repository.GetAfstudeerrichtingen()).ToList();
if (ModelState.IsValid)
{
try
{
MemoryStream target = new MemoryStream();
model.Image.InputStream.CopyTo(target);
byte[] data = target.ToArray();
model.Thumbnail.InputStream.CopyTo(target);
byte[] datatwo = target.ToArray();
users usr = userrepo.FindByUsername(User.Identity.Name);
model.UsernameID = usr.user_id;
repository.AddDeliverable(model.Title, model.Description, model.UsernameID, data, datatwo, model.VideoUrl, model.Afstudeerrichting);
}
catch (ArgumentException ae)
{
ModelState.AddModelError("", ae.Message);
}
return RedirectToAction("Index");
}
return View(model);
}
In sent the values to my repository where I save it in my database.
This is my DeliverableViewModel:
public class DeliverableViewModel
{
[Required]
[Display(Name = "Title")]
public string Title { get; set; }
[Required]
[Display(Name = "Description")]
public string Description { get; set; }
[Required]
[Display(Name = "Thumbnail")]
public HttpPostedFileBase Thumbnail { get; set; }
[Required]
[Display(Name = "Image")]
public HttpPostedFileBase Image { get; set; }
[Required]
[Display(Name = "VideoUrl")]
public string VideoUrl { get; set; }
[Required]
[Display(Name = "AfstudeerrichtingID")]
public int AfstudeerrichtingID { get; set; }
[Required]
[Display(Name = "Afstudeerrichting")]
public IEnumerable<SelectListItem> Items { get; set; }
public long UsernameID { get; set; }
}
Does anyone know what I have to add in my view & controller to make this work?
The values are in my tabel "Afstudeerrichtingen" in my mysql database
- afstuddeerichting_id
- afstudeerrichting_name
Add a dropdownlist in your view:
#Html.DropDownListFor(model => model.AfstudeerrichtingID,
new SelectList(ViewBag.Richtingen,
"AfstudeerrichtingId", "AfstudeerrichtingName"))
Add your Afstudeerrichting collection to the ViewBag in the controller:
ViewBag.Richtingen = afstudeerrichtingen;
Assuming that that collection contains the properties AfstudeerrichtingId and AfstudeerrichtingName, as used in the view.
Another thing to do is change your AfstudeerrichtingID to string, and translate it to/from int in your repository class.
I have a view which accepts the following model:
Inherits="System.Web.Mvc.ViewPage<MVC_WordsByME.Models.JobCreationModel>"
This posts back to the following action:
[HttpPost]
public ActionResult Create(FormCollection formValues)
{
var job = new JobCreationModel();
if (TryUpdateModel(job))
{
_jobRepository.AddJob(job);
_jobRepository.Save();
return RedirectToAction("Index");
}
return View(job);
}
However, on posting back the following exception is thrown:
Unable to cast object of type 'System.Int32' to type 'System.String'.
Description: An unhandled exception occurred during the execution of the current web request.
Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'.
Source Error:
Line 135: {
Line 136: var job = new JobCreationModel();
Line 137: if (TryUpdateModel(job))
Line 138: {
Line 139: _jobRepository.AddJob((Job)job);
Although I can't highlight it here, it's line 137 that the exception occurs on. I can't step into this method, so how can I determine what's causing this exception?
Also, isn't TryUpdateModel supposed to shelter me from any exceptions, simply returning true or false to reflect the result? I wasn't aware that it could throw an exception.
UPDATE: here's the model (both derived and base):
public class JobCreationModel : Job
{
//
// Properties
public SelectList ClientsList { get; private set; }
public SelectList Languages { get; set; }
public SelectList Users { get; set; }
//
// Constructors
public JobCreationModel()
{
var userCurrent = Membership.GetUser();
SentDate = DateTime.Now;
WorkedBy = userCurrent != null ? userCurrent.UserName : string.Empty;
DeadlineDate = DateTime.Now;
ReceivedDate = DateTime.Now;
var clientRepository = new ClientRepository();
ClientsList = new SelectList(clientRepository.GetAllClients(), "ID", "OrganisationName");
var languageRepository = new LanguageRepository();
Languages = new SelectList(languageRepository.GetAllLanguages(), "ID", "Code");
var userList = Membership.GetAllUsers();
Users = new SelectList(userList.Cast<MembershipUser>().ToList(), "UserName", "UserName", userCurrent);
}
public JobCreationModel(Job job)
{
var userCurrent = Membership.GetUser();
Client = job.Client;
ClientName = job.ClientName;
DeadlineDate = job.DeadlineDate;
FixedCost = job.FixedCost;
ID = job.ID;
Invoice = job.Invoice;
JobDescription = job.JobDescription;
JobFileName = job.JobFileName;
LanguageFrom = job.LanguageFrom;
LanguageTo = job.LanguageTo;
PONumber = job.PONumber;
ReceivedDate = job.ReceivedDate;
SentDate = job.SentDate;
WordCost = job.WordCost;
WordCount = job.WordCount;
WorkedBy = job.WorkedBy;
var clientRepository = new ClientRepository();
ClientsList = new SelectList(clientRepository.GetAllClients(), "ID", "OrganisationName");
var languageRepository = new LanguageRepository();
Languages = new SelectList(languageRepository.GetAllLanguages(), "ID", "Code");
var userList = Membership.GetAllUsers();
Users = new SelectList(userList.Cast<MembershipUser>().ToList(), "UserName", "UserName", userCurrent);
}
}
The base type is an entity, and the best way I could think of to show it is to display the XML behind it:
<EntityType Name="Jobs">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="JobDescription" Type="nvarchar" Nullable="false" MaxLength="200" />
<Property Name="ReceivedDate" Type="datetime" Nullable="false" />
<Property Name="DeadlineDate" Type="datetime" Nullable="false" />
<Property Name="SentDate" Type="datetime" Nullable="false" />
<Property Name="Invoice" Type="int" />
<Property Name="WordCount" Type="int" Nullable="false" />
<Property Name="WordCost" Type="float" Nullable="false" />
<Property Name="FixedCost" Type="float" Nullable="false" />
<Property Name="Client" Type="int" Nullable="false" />
<Property Name="JobFileName" Type="nvarchar" Nullable="false" MaxLength="500" />
<Property Name="WorkedBy" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="PONumber" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="LanguageFrom" Type="int" Nullable="false" />
<Property Name="LanguageTo" Type="int" Nullable="false" />
</EntityType>
This then has a buddy class to extend it:
[MetadataType(typeof(JobValidation))]
[Bind(Include = "Client,SentDate,JobFileName,JobDescription,WordCost,WordCount,WorkedBy")]
public partial class Job
{
public IEnumerable Clients
{
get
{
var clientRepository = new ClientRepository();
return clientRepository.GetAllClients();
}
}
public string ClientName { get; set; }
public string SelectedMonth { get; set; }
public string SelectedYear { get; set; }
}
public class JobValidation
{
[Required(ErrorMessage = "Please select a client for the sent job")]
[Range(1, 999999, ErrorMessage = "Please select a client")]
public int Client { get; set; }
[Required(ErrorMessage = "Please enter the completion date for this job")]
[DataType(DataType.Date, ErrorMessage = "The date entered is not in a recognised format")]
public DateTime SentDate { get; set; }
[Required(ErrorMessage = "Job file must have a name")]
[StringLength(500, ErrorMessage = "Job file name must not be longer than 500 characters")]
public string JobFileName { get; set; }
[Required(ErrorMessage = "Job must have a name")]
[StringLength(200, ErrorMessage = "Job name must not be longer than 200 characters")]
public string JobDescription { get; set; }
[Required(ErrorMessage = "Please enter the word cost for the sent job")]
[StringLength(6, ErrorMessage = "The word cost should not exceed 5 digits")]
[DataType(DataType.Currency, ErrorMessage = "The word cost was not recognised as an amount of currency")]
public string WordCost { get; set; }
[Required(ErrorMessage = "Please enter the word count for the sent job")]
[StringLength(8, ErrorMessage = "The word count must not exceed 99999999")]
public string WordCount { get; set; }
public string WorkedBy { get; set; }
}
Finally, here's the relevant part of the view:
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Job Details</legend>
<div class="editor-label">
Job description
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.JobDescription)%>
<%: Html.ValidationMessageFor(model => model.JobDescription)%>
</div>
<div class="editor-label">
PO number
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.PONumber)%>
<%: Html.ValidationMessageFor(model => model.PONumber)%>
</div>
<div class="editor-label">
Date received
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.ReceivedDate)%>
<%: Html.ValidationMessageFor(model => model.ReceivedDate)%>
</div>
<div class="editor-label">
Deadline Date
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DeadlineDate)%>
<%: Html.ValidationMessageFor(model => model.DeadlineDate)%>
</div>
<div class="editor-label">
Date sent
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.SentDate)%>
<%: Html.ValidationMessageFor(model => model.SentDate)%>
</div>
<div class="editor-label">
Is fixed-cost? <input type="checkbox" id="fixed-cost" />
</div>
<div id="word-priced-job">
<div class="editor-label">
Word count
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.WordCount)%>
<%: Html.ValidationMessageFor(model => model.WordCount)%>
</div>
<div class="editor-label">
Word cost
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.WordCost)%>
<%: Html.ValidationMessageFor(model => model.WordCost)%>
</div>
</div>
<div id="fixed-price-job" class="faded">
<div class="editor-label">
Fixed cost
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FixedCost)%>
<%: Html.ValidationMessageFor(model => model.FixedCost)%>
</div>
</div>
<div class="editor-label">
Languages
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.LanguageFrom, Model.Languages, "-- Select --") %><%: Html.ValidationMessageFor(model => model.LanguageFrom)%>
<span> - to - </span>
<%: Html.DropDownListFor(model => model.LanguageTo, Model.Languages, "-- Select --") %><%: Html.ValidationMessageFor(model => model.LanguageTo)%>
</div>
<div class="editor-label">
Client
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.Client, Model.ClientsList, "-- Select --") %> <%: Html.ActionLink("Create a new client", "Create", "Clients") %>
<%: Html.ValidationMessageFor(model => model.Client)%>
</div>
<div class="editor-label">
Job file name
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.JobFileName) %>
<%: Html.ValidationMessageFor(model => model.JobFileName)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.WorkedBy)%>
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.WorkedBy, Model.Users) %>
</div>
<p>
<input id="btnSave" type="submit" value="Save" />
</p>
</fieldset>
<% } %>
No idea why this exception occurs without seeing your model and view code but try simplifying your action like this:
[HttpPost]
public ActionResult Create(JobCreationModel job)
{
if (!ModelState.IsValid)
{
return View(job);
}
_jobRepository.AddJob(job);
_jobRepository.Save();
return RedirectToAction("Index");
}
I've changed:
[StringLength(3)]
public int? GroupID { get; set; }
to:
public int? GroupID { get; set; }
So the StringLength attribute made problems, because GroupID was int? and as it seems StringLength attribute is valid only for strings.