Custom Validation based on drop down selected value in MVC - asp.net-mvc

I want validate a property using data annotation based on the value of another property.
I have a people model--
public class People
{
[DisplayName("Your Name")]
[Required]
public string Name { get; set; }
[Required]
public string Gender { get; set; }
[DisplayName("Your Age")]
[Required]
// Another Attribute here for my custom validation
public int Age { get; set; }
}
And Index :
public ActionResult Index()
{
IList<SelectListItem> types = new List<SelectListItem>();
types.Add(new SelectListItem() { Text = "Male", Value = "M" });
types.Add(new SelectListItem() { Text = "Female", Value = "F" });
ViewBag.ItemTypes = types;
return View();
}
'Gender' is bound to a drop down list and based on the selected Gender I want to validate 'Age' property.
If Male is selected then the Age range must be between 22 and 60.
If Female is selected then the Age range must be between 18 and 58.
There must be a custom validation attribute for this but I am not able to figure it out.
My View:
#using (Html.BeginForm("Index", "Test", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TimeRecord</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Gender, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Gender, (IEnumerable<SelectListItem>)ViewBag.ItemTypes, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Age, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Age, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Age, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}

You can create a custom validation attribute as it works well for validating individual properties (individual property-level validation), check the below code snippet.
namespace SO.Models
{
using Helpers;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class Person
{
// code omitted for brevity
[DisplayName("Your Age")]
[Required]
[PersonAge(minMaleAge: 22, maxMaleAge: 60, minFemaleAge: 18, maxFemaleAge: 58)]
public int Age { get; set; }
}
}
namespace SO.Helpers
{
using Models;
using System.ComponentModel.DataAnnotations;
public class PersonAgeAttribute : ValidationAttribute
{
private const string _validationMessage = "Age should be between {0} and {1}";
private int _minMaleAge;
private int _maxMaleAge;
private int _minFemaleAge;
private int _maxFemaleAge;
public PersonAgeAttribute(int minMaleAge, int maxMaleAge, int minFemaleAge, int maxFemaleAge)
{
_minMaleAge = minMaleAge;
_maxMaleAge = maxMaleAge;
_minFemaleAge = minFemaleAge;
_maxFemaleAge = maxFemaleAge;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Person person = (Person)validationContext.ObjectInstance;
if (person.Gender == "M" && (person.Age < _minMaleAge || person.Age > _maxMaleAge))
{
return new ValidationResult(GetErrorMessage(person.Gender));
}
else if (person.Gender == "F" && (person.Age < _minFemaleAge || person.Age > _maxFemaleAge))
{
return new ValidationResult(GetErrorMessage(person.Gender));
}
return ValidationResult.Success;
}
private string GetErrorMessage(string gender)
{
if (gender == "M")
{
return string.Format(_validationMessage, _minMaleAge, _maxMaleAge);
}
else
{
return string.Format(_validationMessage, _minFemaleAge, _maxFemaleAge);
}
}
}
}
Alternatively IValidatableObject interface can be implemented to do class-level validation by implementing its Validate method. For more information check Class-Level Model Validation

Based on your requirement as per my understanding the solution may be like this.
For server side validation create your own custom side validation attribute. To enable client side validation inherit 'IClientValidatable'.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
public class AgeForGenderAttribute : ValidationAttribute, IClientValidatable
{
private string _PropertyToCompare { get; set; }
private string CurrentPropertyValue { get; set; }
public int _MinAgeForMale { get; set; }
public int _MaxAgeForMale { get; set; }
public int _MinAgeForFemale { get; set; }
public int _MaxAgeForFemale { get; set; }
string relevantErrorMessage { get; set; }
public AgeForGenderAttribute(string PropertyToCompare, int MinAgeForMale, int MaxAgeForMale, int MinAgeForFemale, int MaxAgeForFemale, string validationMessage)
{
this._PropertyToCompare = PropertyToCompare;
this._MinAgeForMale = MinAgeForMale;
this._MaxAgeForMale = MaxAgeForMale;
this._MinAgeForFemale = MinAgeForFemale;
this._MaxAgeForFemale = MaxAgeForFemale;
ErrorMessage = validationMessage;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var comparePropertyInfo = validationContext.ObjectType.GetProperty(_PropertyToCompare);
object dependentPropertyValue = comparePropertyInfo.GetValue(validationContext.ObjectInstance, null);
CurrentPropertyValue = dependentPropertyValue.ToString();
var currentValue = (int)value;
if (dependentPropertyValue != null)
{
switch (CurrentPropertyValue)
{
case "M":
if (currentValue < _MinAgeForMale || currentValue > _MaxAgeForMale)
{
ErrorMessage = string.Format(ErrorMessage, _MinAgeForMale, _MaxAgeForMale);
return new ValidationResult(ErrorMessage);
}
break;
case "F":
if (currentValue < _MinAgeForFemale || currentValue > _MaxAgeForFemale)
{
ErrorMessage = string.Format(ErrorMessage, _MinAgeForMale, _MaxAgeForMale);
return new ValidationResult(ErrorMessage);
}
break;
}
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rules = new ModelClientValidationRule
{
ValidationType = "conditionalrange",
ErrorMessage = ErrorMessage
};
rules.ValidationParameters.Add("condiotionalpropertyname", _PropertyToCompare);
rules.ValidationParameters.Add("minageformale", _MinAgeForMale);
rules.ValidationParameters.Add("maxageformale", _MaxAgeForMale);
rules.ValidationParameters.Add("minageforfemale", _MinAgeForFemale);
rules.ValidationParameters.Add("maxageforfemale", _MaxAgeForFemale);
yield return rules;
}
}
Your js:
$(function () {
$.validator.addMethod("conditionalrange", function (value, element, params) {
var condiotionalpropertyname = $('#' + params.condiotionalpropertyname).val();
var retVal = true;
switch (condiotionalpropertyname) {
case 'M':
if (value < params.minageformale || value > params.maxageformale) {
retVal = false;
}
break;
case "F":
if (value < params.minageforfemale || value > params.maxageforfemale) {
retVal = false;
}
break;
}
return retVal;
});
$.validator.unobtrusive.adapters.add("conditionalrange", ['condiotionalpropertyname', 'minageformale', 'maxageformale', 'minageforfemale', 'maxageforfemale'],
function (options) {
options.rules['conditionalrange'] = {
condiotionalpropertyname: options.params.condiotionalpropertyname,
minageformale: options.params.minageformale,
maxageformale: options.params.maxageformale,
minageforfemale: options.params.minageforfemale,
maxageforfemale: options.params.maxageforfemale
};
options.messages['conditionalrange'] = options.message;
}
);
}(jQuery));
It will work exactly as per your requirement.Make sure that you have included the all relevant js.
Property:
[DisplayName("Your Age")]
[Required]
[AgeForGender("Gender", 18, 45, 22, 60, "Age should be between {0} and {1}")]
public int Age { get; set; }

Related

How to store and display SelectList data

I am using SelectList to populate dropdownlists in my view. It works for the Create and Edit views to store ID value data in a table. How do I retrieve the 'Name' value to display in a Details view?
Model
Public Class Employee {
[Key]
public int ID { get; set;}
public string UserName {get; set; }
public byte Gender { get; set; }
}
ViewModel
public class EmployeeEditViewModel {
public int ID { get; set; }
public string UserName { get; set; }
public SelectList GenderList { get; set; }
public EmployeeEditViewModel () {
GenderList = CommonHelper.GenderList(null);
}
}
Helper
public static SelectList GenderList(object selected)
{
return new SelectList(new[]
{
new { Value = 0, Name = "Male" },
new { Value = 1, Name = "Female" }
}
, "Value", "Name", selected);
}
Edit View
#model Models.ViewModel.EmployeeEditViewModel
#using (Html.BeginForm()) {
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.UserName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.GenderList, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Gender, Model.GenderList, "- Select -", new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.GenderList, "", new { #class = "text-danger" })
</div>
</div>
}
Controller
[HttpPost]
public ActionResult CreateEmployee(EmployeeEditViewModel emProfile)
{
try
{
if (ModelState.IsValid)
{
Employee newUser = new Employee();
newUser.UserName = emProfile.UserName;
newUser.Gender = emProfile.Gender;
userRepository.Add(newUser);
userRepository.SaveChanges();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{ }
return View(emProfile);
}
So far it works great, I am able to create, edit Employee records and 1 or 0 is stored in the table for the gender.
But when I want to display the employee data in a details view how do I get the text 'Male' or 'Female'?
I ended up creating a helper method to retrieve the text.
public static string GetTextFromSelectList(int id, string listName)
{
string selectedText = string.Empty;
SelectListItem selectedItem;
switch (listName)
{
case "Gender":
selectedItem = Helper.CommonHelper.GenderList(null).FirstOrDefault(x => x.Value == id.ToString());
selectedText = selectedItem == null ? null : selectedItem.Text;
break;
default:
selectedText = null;
break;
}
return selectedText;
}

How do I to get id of an enum value with #DropDownListFor?

I created an Enum and the values has id now I need to get the id in #Html.DropDownListFor but I don't know how to do it.
How could I get the id of Enum ?
Enum
public enum GainLosses
{
Gain = 1,
Loss = 2
};
Model
//Gain/Loss
[DisplayName("Gain/Loss")]
public int gainLoss { get; set; }
public IEnumerable<SelectListItem> gainLosses
{
get { return CustomEnum.Enum.GetItems<GainLosses>().Select(x => new SelectListItem() { Text = x.ToString(), Value = x.ToString() }); }
}
//
HTML
<div class="form-group">
<label for="#Html.IdFor(model => model.gainLoss)" class="cols-sm-2 control-label">Gain/Loss <img src="~/Imagens/required.png" height="6" width="6" title="requerido"></label>
#Html.DropDownListFor(model => model.gainLoss, Model.gainLosses, new { Class = "form-control" })
#Html.ValidationMessageFor(model => model.gainLoss, "", new { #class = "text-danger" })
</div><!--/Gain/Loss-->
I've already solved the problem.
[DisplayName("Gain/Loss")]
public int gainLoss { get; set; }
public IEnumerable<SelectListItem> gainLosses
{
get { return CustomEnum.Enum.GetItems<GainLosses>().Select(x => new SelectListItem() { Text = x.ToString(), Value = ((int)x).ToString() }); }
}
//

how to upload image in ActionResult asp.net mvc?

I want set image to my post but I can't.all model field is fill but image field is null
my model class:
public class Game
{
public Game()
{
Platforms = new List<Platform>();
}
[Key]
public int GameID { get; set; }
public string Name { get; set; }
public string Image { get; set; }
[AllowHtml]
public string Description { get; set; }
public DateTime PublishDate { get; set; }
public virtual ICollection<Platform> Platforms { get; set; }
}
my controller class :
public ActionResult Create_post(Game model,int[] platformsIds)
{
if (ModelState.IsValid)
{
foreach (var pId in platformsIds)
{
var platform = _repository.Get<Platform>(pId);
model.Platforms.Add(platform);
}
_repository.Add<Game>(model);
return RedirectToAction("Index");
}
ViewBag.Platforms = _repository.GetAll<Platform>().ToList();
ViewBag.HtmlContent = model.Description;
return View(model);
}
thank you
you just check image url before save your model
in your view you must have this code
<div class="form-group">
#Html.LabelFor(model => model.Image, htmlAttributes: new { #class = "control-label col-md-1" })
<div class="col-md-4">
<div class="col-md-6 col-md-push-0">
<input type="file" class="form-control" name="ImageUrl" id="ImageUrl" />
</div>
#Html.ValidationMessageFor(model => model.Image, "", new { #class = "text-danger" })
</div>
</div>
in your controller you must change your code
public ActionResult Create_post(Game model,int[] platformsIds,HttpPostedFileBase ImageUrl)
{
if (ModelState.IsValid)
{
foreach (var pId in platformsIds)
{
var platform = _repository.Get<Platform>(pId);
model.Platforms.Add(platform);
}
if (ImageUrl != null && ImageUrl.ContentLength > 0)
{
var uploadDir = "~/images/Games/"; // your location for save images
string image = Guid.NewGuid().ToString() + ImageUrl.FileName;
var imagePath = Path.Combine(Server.MapPath(uploadDir),image);
ImageUrl.SaveAs(imagePath);
model.Image = image;
}
_repository.Add<Game>(model);
return RedirectToAction("Index");
}
ViewBag.Platforms = _repository.GetAll<Platform>().ToList();
ViewBag.HtmlContent = model.Description;
return View(model);
}

ID identity field value does not increase

I have a form to bind id field as hidden value. But in controller, the id (key, auto identity increment) field always 0. Below is my code:
Model.cs
public partial class A
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[StringLength(255)]
[Display(Name = "Institution Name")]
[Required]
public string InstitutionName { get; set; }
[Display(Name = "Public")]
[DefaultValue(false)]
public bool Category1 { get; set; }
[Display(Name = "Private")]
[DefaultValue(false)]
[Display(Name = "Online")]
[DefaultValue(false)]
public bool Category3 { get; set; }
[
[Display(Name = "Active?")]
[DefaultValue(false)]
public bool active { get; set; }
public A()
{
Category1 = false;
Category2 = false;
Category3 = false;
active = true;
}
}
Controller:
...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,InstitutionName,Category1,Category2,Category3,active")] A A)
{
if (ModelState.IsValid)
{
db.A.Add(A);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(A);
}
}
...
View - Create.cshtml:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TransferSearch_revised</h4>
<hr />
#Html.HiddenFor(model=> model.id)
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.InstitutionName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.InstitutionName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.InstitutionName, "", new { #class = "text-danger" })
</div>
</div>
...
The id value either 0 or empty. What's wrong with my code? Thanks.

Issue extending the base EDMX model and calling the functions in the data model

I am writing a solution using MVC with scaffolding. It uses Entity Framework v6 and is database first in design. The base data model (ServiceAccountFilter) is extended by the data model (FilterModel). There is some logic in the FilterModel but the properties are all inherited from the base model. It seems as though the controller insists on using the base model. When I change the return to use the FilterModel, I get an error that the view requires the base model and then the functions in the FilterModel are not visible in the views? Not sure how to handle this?
Base Model:
namespace FHN.ARX.AdminWeb
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
public partial class ServiceAccountFilter
{
[DisplayName("Filter ID")]
public virtual int FilterId { get; set; }
[DisplayName("Filter Name")]
public virtual string FilterName { get; set; }
[DisplayName("Service Account")]
public virtual string ServiceAccount { get; set; }
[DisplayName("Doc Type")]
public virtual string DocType { get; set; }
[DisplayName("Doc Type ID")]
public virtual Nullable<int> DocTypeId { get; set; }
[DisplayName("Doc Name ID")]
public virtual string DocNameId { get; set; }
[DisplayName("Last Modified By ID")]
public virtual string LastModifiedById { get; set; }
[DisplayName("Last Modified By")]
public virtual string LastModifiedByName { get; set; }
[DisplayName("Last Modified")]
public virtual Nullable<System.DateTime> LastModified { get; set; }
[DisplayName("Months To Return")]
public virtual Nullable<int> MonthsToReturn { get; set; }
}
}
FilterModel
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace FHN.ARX.AdminWeb.Models
{
public class FilterModel : ServiceAccountFilter
{
[DisplayName("Filter ID")]
public override int FilterId { get; set; }
[DisplayName("Filter Name")]
public override string FilterName { get; set; }
[DisplayName("Service Account")]
public override string ServiceAccount { get; set; }
[DisplayName("Doc Type")]
public override string DocType { get; set; }
[DisplayName("Doc Type ID")]
public override Nullable<int> DocTypeId { get; set; }
[DisplayName("Doc Name ID")]
public override string DocNameId { get; set; }
[DisplayName("Last Modified By ID")]
public override string LastModifiedById { get; set; }
[DisplayName("Last Modified By")]
public override string LastModifiedByName { get; set; }
[DisplayName("Last Modified")]
public override Nullable<System.DateTime> LastModified { get; set; }
[DisplayName("Months To Return")]
public override Nullable<int> MonthsToReturn { get; set; }
public bool Selected { get; set; }
public string Checkboxes { get; set; }
public IEnumerable<SelectListItem> DocTypesList(string id)
{
using (var db = new ARXEntities())
{
var docType = new List<SelectListItem>();
docType = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == id
orderby t.DocType
select new { t.DocType, t.DocTypeId }).Distinct().Select(x => new SelectListItem() { Text = x.DocType, Value = x.DocTypeId.ToString() }).OrderBy(x => x.Text).ToList();
return docType;
}
}
public IEnumerable<SelectListItem> DocNamesList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
var loggedInUser = "C2693"; // HttpContext.Current.User.Identity.Name.Split('\\')[1];
docName = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == loggedInUser
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> ServiceAccountList()
{
using (var db = new ARXEntities())
{
var sa = new List<SelectListItem>();
sa = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN.StartsWith("sa_")
orderby t.UserDN
select new { t.UserDN }).Distinct().Select(x => new SelectListItem() { Text = x.UserDN, Value = x.UserDN }).OrderBy(x => x.Text).ToList();
return sa;
}
}
public IEnumerable<SelectListItem> DocNamesByDocTypeIdList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.vwMapDocNamesToSecurityUsers
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> GetDocNamesForFilterId(int? id)
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.ServiceAccountFilters
where t.FilterId == id
select new { t.DocNameId, t.FilterId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocNameId,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocNameId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
return docName;
}
}
}
}
Controller Edit Action
public ActionResult Edit(int? id)
{
if (id == null)
{
var saf = new FilterModel();
return View(saf);
}
FilterModel serviceAccountFilter = (FilterModel)db.ServiceAccountFilters.Find(id); <----Tried casting here, but still didnt work.
if (serviceAccountFilter == null)
{
return HttpNotFound();
}
return View(serviceAccountFilter);
}
Edit View
#model FHN.ARX.AdminWeb.Models.FilterModel
#{
ViewBag.Title = "Edit A Filter";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="pageTitle">Filter Maintenance</div>
#using (Html.BeginForm(new { id = "filterForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.FilterId)
#Html.HiddenFor(model => model.LastModified)
#Html.HiddenFor(model => model.LastModifiedById)
#Html.HiddenFor(model => model.LastModifiedByName)
<div class="ddlGroups, btmMarg-15">
#Html.DropDownListFor(m => m.ServiceAccount, Model.ServiceAccountList(), "Select a Service Account")
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.ServiceAccount, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.ServiceAccount, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.DocTypeId, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.DocTypeId, new { htmlAttributes = new { #class = "form-control" } })
</div>
<p class="leftMarg-15 text-default" id="docNamesHdrText">Select the document names to be included in the filter.</p>
<div class="ckDocNames">
#foreach (var dn in Model.DocNamesByDocTypeIdList())
{
<div class="checkboxContainer">
<input class="ckBoxes" type="checkbox" name="DocNameId" value="#dn.Value" dtid="#dn.Group.Name" />#dn.Text<br />
</div>
}
</div>
<div class="form-group, col-md-10, btmMarg-15" id="monthsGroup">
#Html.LabelFor(model => model.MonthsToReturn, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.MonthsToReturn, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MonthsToReturn, "", new { #class = "text-danger" })
</div>
<div class="form-group, col-md-10, btmMarg-15" id="filterNameGroup">
#Html.LabelFor(model => model.FilterName, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.FilterName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FilterName, "", new { #class = "text-danger" })
</div>
<br />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" id="modSaveButton" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "ActiveFilters") |
#Html.ActionLink("Admin Home", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
this is an example of using a viewmodel on your case ... (may be it's not prefect but just a hint on your way)
namespace FHN.ARX.AdminWeb
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
public partial class ServiceAccountFilter
{
public int FilterId { get; set; }
public string FilterName { get; set; }
public string ServiceAccount { get; set; }
public string DocType { get; set; }
public Nullable<int> DocTypeId { get; set; }
public string DocNameId { get; set; }
public string LastModifiedById { get; set; }
public string LastModifiedByName { get; set; }
public Nullable<System.DateTime> LastModified { get; set; }
public Nullable<int> MonthsToReturn { get; set; }
}
}
no need for the filter model now and instead of that put all the logic in the controller under a heper region
#region Helpers
public IEnumerable<SelectListItem> DocTypesList(string id)
{
using (var db = new ARXEntities())
{
var docType = new List<SelectListItem>();
docType = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == id
orderby t.DocType
select new { t.DocType, t.DocTypeId }).Distinct().Select(x => new SelectListItem() { Text = x.DocType, Value = x.DocTypeId.ToString() }).OrderBy(x => x.Text).ToList();
return docType;
}
}
public IEnumerable<SelectListItem> DocNamesList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
var loggedInUser = "C2693"; // HttpContext.Current.User.Identity.Name.Split('\\')[1];
docName = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN == loggedInUser
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> ServiceAccountList()
{
using (var db = new ARXEntities())
{
var sa = new List<SelectListItem>();
sa = (from t in db.vwMapDocNamesToSecurityUsers
where t.UserDN.StartsWith("sa_")
orderby t.UserDN
select new { t.UserDN }).Distinct().Select(x => new SelectListItem() { Text = x.UserDN, Value = x.UserDN }).OrderBy(x => x.Text).ToList();
return sa;
}
}
public IEnumerable<SelectListItem> DocNamesByDocTypeIdList()
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.vwMapDocNamesToSecurityUsers
select new { t.DocName, t.DocNameId, t.DocTypeId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocName,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocTypeId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
var docCount = docName.Count();
return docName;
}
}
public IEnumerable<SelectListItem> GetDocNamesForFilterId(int? id)
{
using (var db = new ARXEntities())
{
IEnumerable<SelectListItem> docName = new List<SelectListItem>();
docName = (from t in db.ServiceAccountFilters
where t.FilterId == id
select new { t.DocNameId, t.FilterId }).Distinct().Select(x => new SelectListItem()
{
Text = x.DocNameId,
Value = x.DocNameId.ToString(),
Group = new SelectListGroup() { Name = x.DocNameId.ToString() }
}).Distinct().OrderBy(x => x.Text).ToList();
return docName;
}
}
#endregion
in your controller Edit Action
public ActionResult Edit(int? id)
{
if (id == null)
{
var saf = new FilterModel();
return View(saf);
}
var serviceAccountFilter = db.ServiceAccountFilters.Find(id)
if (serviceAccountFilter == null)
{
return HttpNotFound();
}
var model = new FilterViewModel
{
FilterId = serviceAccountFilter.FilterId,
FilterName = serviceAccountFilter.FilterName,
ServiceAccount = serviceAccountFilter.ServiceAccount,
DocType = serviceAccountFilter.DocType,
DocTypeId = serviceAccountFilter.DocTypeId,
DocNameId = serviceAccountFilter.DocNameId,
LastModifiedById = serviceAccountFilter.LastModifiedById,
LastModifiedByName = serviceAccountFilter.LastModifiedByName,
LastModified = serviceAccountFilter.LastModified,
MonthsToReturn = serviceAccountFilter.MonthsToReturn,
ServiceAccountList = ServiceAccountList(),
DocNamesByDocTypeIdList = DocNamesByDocTypeIdList()
};
return View(model);
}
and here is a ViewModel lets say it's name will be FilterViewModel
public class FilterModel
{
[DisplayName("Filter ID")]
public int FilterId { get; set; }
[DisplayName("Filter Name")]
public string FilterName { get; set; }
[DisplayName("Service Account")]
public string ServiceAccount { get; set; }
[DisplayName("Doc Type")]
public string DocType { get; set; }
[DisplayName("Doc Type ID")]
public Nullable<int> DocTypeId { get; set; }
[DisplayName("Doc Name ID")]
public string DocNameId { get; set; }
[DisplayName("Last Modified By ID")]
public string LastModifiedById { get; set; }
[DisplayName("Last Modified By")]
public string LastModifiedByName { get; set; }
[DisplayName("Last Modified")]
public Nullable<System.DateTime> LastModified { get; set; }
[DisplayName("Months To Return")]
public Nullable<int> MonthsToReturn { get; set; }
public IEnumerable<SelectListItem> ServiceAccountList { get; set; }
public IEnumerable<SelectListItem> DocNamesByDocTypeIdList { get; set; }
}
and then your Edit View will be
#model FilterViewModel // check the name space
#{
ViewBag.Title = "Edit A Filter";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="pageTitle">Filter Maintenance</div>
#using (Html.BeginForm(new { id = "filterForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.FilterId)
#Html.HiddenFor(model => model.LastModified)
#Html.HiddenFor(model => model.LastModifiedById)
#Html.HiddenFor(model => model.LastModifiedByName)
<div class="ddlGroups, btmMarg-15">
#Html.DropDownListFor(m => m.ServiceAccount, Model.ServiceAccountList(), "Select a Service Account")
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.ServiceAccount, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.ServiceAccount, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="ddlGroups, col-md-10, btmMarg-15">
#Html.LabelFor(model => model.DocTypeId, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.DocTypeId, new { htmlAttributes = new { #class = "form-control" } })
</div>
<p class="leftMarg-15 text-default" id="docNamesHdrText">Select the document names to be included in the filter.</p>
<div class="ckDocNames">
#foreach (var dn in Model.DocNamesByDocTypeIdList())
{
<div class="checkboxContainer">
<input class="ckBoxes" type="checkbox" name="DocNameId" value="#dn.Value" dtid="#dn.Group.Name" />#dn.Text<br />
</div>
}
</div>
<div class="form-group, col-md-10, btmMarg-15" id="monthsGroup">
#Html.LabelFor(model => model.MonthsToReturn, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.MonthsToReturn, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MonthsToReturn, "", new { #class = "text-danger" })
</div>
<div class="form-group, col-md-10, btmMarg-15" id="filterNameGroup">
#Html.LabelFor(model => model.FilterName, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.FilterName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FilterName, "", new { #class = "text-danger" })
</div>
<br />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" id="modSaveButton" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "ActiveFilters") |
#Html.ActionLink("Admin Home", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}

Resources