validate dropdown in MVC - asp.net-mvc

Model
[Required]
[Display(Name = "Source")]
[Range(typeof(string), "0","10", ErrorMessage = "Please select Source")]
public string Source { get; set; }
View
#Html.DropDownListFor(model => model.Source, new SelectList(new[]
{
new {ID="select",Name="Select"},
new{ID="Facebook",Name="Facebook"},
new{ID="Twitter",Name="Twitter"},
new{ID="LinkedIn",Name="LinkedIn"},
},
"ID", "Name", 1), new { style = "height:24px;" })
How can I validate this using data annotations? I need to store ID as text like Facebook in db.

You can use IValidatableObject interface and implement your own validation of your model class.
How do I use IValidatableObject?

#Html.DropDownListFor(model => model.Source, new SelectList(new[]
{
new{ID="Facebook",Name="Facebook"},
new{ID="Twitter",Name="Twitter"},
new{ID="LinkedIn",Name="LinkedIn"},
},
"ID", "Name", 1),"Select", new { style = "height:24px;" })
I have given like this. Its working fine now.

You have already decorated your model with data annotations. Now you only need to put unobtrusive jquery scripts to enable your validations on client side. Server side validation should work as is. I fail to understand the rationale of Range Attribute on select list though.

Related

How to make Sorting and Filtering working for viewmodel column in InLine editing of Kendo UI MVC grid signalR?

Sorting and Filtering are not working on the column bound with ViewModel entity. It is working fine with other columns.
Sample Grid Code:
#(Html.Kendo().Grid<abc.Models.ShippingViewModel>()
.Name("ShippingGrid")
.Columns(c =>
{
c.Bound(m => m.Id).Hidden();
c.Bound(m => m.LocationViewModel)
.ClientTemplate("#=LocationViewModel.LocationName#")
.Title("Pickup Location")
.HeaderHtmlAttributes(new { #title = "Pickup Loactions" });
c.Bound(m => m.UnitsShipped)
.HtmlAttributes(new { style = "text-align:right" })
.HeaderHtmlAttributes(new { title = "Units Shipped", style = "text-align: right" });
Model:
public class InHouseShippingViewModel
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required]
[UIHint("ShippingLocationEditor")]
public LocationViewModel LocationViewModel { get; set; }
[Required]
[Display(Name = "Units Shipped")]
[UIHint("ComanexIntegerEditor")]
[DisplayFormat(DataFormatString = GlobalVaribleDeclarations.displayFormatForInteger)]
public int UnitsShipped { get; set; }
}
Hub/Controller code:
public IEnumerable<ShippingViewModel> Shipping_Read()
{
var queryResult = ShippingRepository.Shipping_Read();
return queryResult;
}
Here Sorting is working fine on "UnitShipped" column whereas it is not working on "LocationViewModel" column. If I use c.Bound(m => m.LocationViewModel.LocationName), sorting & filtering are working fine but then I am not able to get the DropDownEditor for the this column when editing a record. I am using "InLine" editing here.
I have tested this with "PopUp" editing and everything working fine. I would like to achieve this with "InLine" editing though.
Please advise what should I do to achieve "InLine" editing with Cascading dropdown and Sorting all together. thanks!
there is a mix of things to do. First for filtering etc you need to use the datasourcerequest parameter as in normal ajax calls but then you will find out that sorting does not work.
public DataSourceResult Read(MyDataSourceRequest request)
{
}
this does not work since the kendo regular use 'sorts' for passing a collection of sort and this collection is passed by the signalr datasource as 'sort' (no s). you will have to use the dynamic linq nuget package which has a custom datasource request that will work with signalr. Please copy their code in your solution for the custom datarequest object and the slightly todatasourceresult syntax.
http://www.telerik.com/forums/problems-with-grid-using-signalr-and-serverfiltering-sorting-and-paging
relaying information needs a wrap in datasourceresult as well
Clients.Others.update(WrapInDataSourceResult(item));
public DataSourceResult WrapInDataSourceResult(EmployeeViewModel item)
{
return new DataSourceResult
{
Data = new[]
{
item
}
};
}
also you need to activate server side options serverpaging(true) etc
.SignalR()
.AutoSync(true)
.Sort(c => c.Add(e => e.FullName).Ascending())
.ServerAggregates(true)
.ServerPaging(true)
.ServerSorting(true)
.ServerGrouping(true)
and in the schema
.Schema(schema => schema
.Data("Data")
.Total("Total")
.Aggregates("Aggregates")
.Groups("Groups")
.Model(model =>
{
model.Id(m => m.EmployeeId);
})

Cascading dripdown list in MVC4 Razor

I have 3 tables country , state , city .
I want cascading drop down list as usual.
How can i do that without using the LINQ.
I don't know that how to start. I want to do that using RAZOR. It is okay if it is in JQUERY or JSON.
How to start that.
Thanks in advance.
Can i do that using stored procedure.
tables are:-
user:
name
cityid
country:
id stateid name
state
stateid cityid name
city
cityid name .
i have tried nothing because i don't know where to start.
A general approach to creating cascading selects
Create a view model containing the properties you want to display, including properties for the country and state ID's and a SelectList for the Country options
In your view render selects using #HtmlDropDownFor() for the Country, Sate and Property ID's (the Country select will be populated; the others will be empty)
Using jQuery, in the Country change event, use an AJAX call to an action method which returns a list of States based on the selected Country (either return html to replace the City select, or return JSON to create a new set of option elements.
Repeat the above when a State is selected (to populate the City select)
No one here will provide you complete code like you are asking in your question but usage of dropdown i m explaining below :
Basic and cleanest way to make a dropdown in MVC is like :
Model :
public List<SelectListItem> ItemTypes { get; set; }
public int ItemVal { get; set; }
In your [HttpGet] Controller just bind `Model.ItemTypes` with values
View:
#Html.DropDownListFor(m => m.ItemVal , new SelectList(Model.ItemTypes , "Value", "Text"), " -----Select List----- ")
here in above example the 3rd overload of DropDownListFor() i.e. " -----Select List----- " will be the initial selected item of your dropdown with value equal to ' '.
At Controller during POST ItemVal will have selected dropdown value.
The above shown code is best and simplest way to bind Dropdownlist in MVC.
See this exmple. You'll have an idea. I'm just showing sample which is not tested.
public ActionResult Index()
{
var countries = new List<string> { "USA", "India" };
ViewBag.Countries = new SelectList(countries);
return View();
}
public ActionResult GetStates(string country)
{
//perform filter here based on country
return Json(new[] {
new { Id = 1, Value = "State 1" },
new { Id = 2, Value = "State 2" },
new { Id = 3, Value = "State 3" },
}, JsonRequestBehavior.AllowGet);
}
View Page
<div>Select country:</div>
<div>#Html.DropDownList("country",
ViewBag.Countries as SelectList,
"Please select",
new { id = "country" })
</div>
<div>Select state:</div>
<div>
<select id="state"></select>
</div>
On Country selection, do ajax call and get related states.
<script type="text/javascript">
$(function () {
$('#country').on('change', function () {
$.getJSON('#Url.Action("GetStates")', function (result) {
var ddl = $('#state');
ddl.empty();
$(result).each(function () {
$(document.createElement('option'))
.attr('value', this.Id)
.text(this.Value)
.appendTo(ddl);
});
});
});
})
</script>

How do I apply the jQuery unobtrusive validation to a DropDownList editor template?

Too many people have told me to apply the required class to make the field required. I don't want the good ol' required attribute; I want the new attribute sets for validation. This is what I've tried without success:
This is my editor template:
#using Comair.RI.UI.Core
#{
var list = this.GetModelSelectList();
var listWithSelected = new SelectList(list.Items, list.DataValueField, list.DataTextField, Model);
}
#if (ViewData.ModelMetadata.IsRequired)
{
//var att = "data-val-required=\"string.Format("The {0} field is required", ViewData.ModelMetadata.DisplayName)
var att = string.Format("The {0} field is required.", ViewData.ModelMetadata.DisplayName);
#Html.DropDownListFor(m => Model, listWithSelected, " - select - ",
new Dictionary<string, object> {{"data-val-number=", "The field " + ViewData.ModelMetadata.DisplayName + " must be a number."}, {"data-val", true}, {"data-val-required", att}})
}
Simply decorate the corresponding view model property with the desired validation attributes. For example:
public class Core
{
[Required]
public int? Id { get; set; }
}
and then:
#using Comair.RI.UI.Core
#{
var list = this.GetModelSelectList();
var listWithSelected = new SelectList(list.Items, list.DataValueField, list.DataTextField, Model);
}
#if (ViewData.ModelMetadata.IsRequired)
{
#Html.DropDownListFor(m => m.Id, listWithSelected, " - select - ")
}
Also notice that the first argument you are passing to the DropDownListFor helper must represent a lambda expression pointing to a simple scalar property type (such as integer or string). That's why in my example I have illustrated how to apply the Required attribute to the corresponding Id property on your view model and then simply bind the DropDownList to it. Then the helper will take care to generate all the necessary attributes for unobtrusive validation to work. In your example you were binding the dropdownlist to the model with m => Model which first is an incorrect lambda expression because you are capturing the Model value from the outside and even worse it is a complex type which is not very compatible with the helper.
There's just one thing you should be aware of. If this template is not called within a form (Html.BeginForm or Ajax.BeginForm) the helper will not emit client side validation attributes such as data-required and so on. You could workaround this issue by instantiating the FormContext if not present:
#if (ViewContext.FormContext == null)
{
ViewContext.FormContext = new FormContext();
}
#Html.DropDownListFor(m => m.Id, listWithSelected, " - select - ")
This will ensure that the helper will always emit the validation attributes.

Unable to save Enum values into entity field from DropDownList - EF Code First MVC3

I have a DropDownList that contains the correct items and values when the view is rendered but the selected value is not being saved within the designated entity field Garage. Currently the value being saved and returned is 0 (None) in both create or edit post methods. I'm sure this is something simple but I can't figure it out... Thanks in advance!
The Model Class:
public enum GarageType { None = 0, One = 1, Two = 2, Three = 3, Four = 4 }
public int Garage { get; set; }
[NotMapped]
public GarageType GarageEnumValue
{
get { return (GarageType)Garage; }
set{ Garage = (int)value; }
}
The Control Create and Edit methods both look like this:
var statuses = from Property.GarageType s in Enum.GetValues(typeof(Property.GarageType))
select new { ID = (int)s, Name = s.ToString() };
ViewBag.GarageId = new SelectList(statuses, "ID", "Name", statuses.FirstOrDefault().ID);
Last the View:
#Html.DropDownList("GarageId", String.Empty)
Use the following overload of DropDownList method
#Html.DropDownList("GarageEnumValue", (SelectList)ViewBag.GarageId, String.Empty)
If you have a strongly type model use
#Html.DropDownListFor(m => m.GarageEnumValue, (SelectList)ViewBag.GarageId, String.Empty)
The first argument in both cases should be the property that you are going to bind the list.

Can I send a SelectList through the UIHint Control Parameters?

Can I send a SelectList through a Data Annotation? Something like...
[UIHint("DropDownList", "", new SelectList(new[] {"one","two","three"}))]
public virtual int? OptionID { get; set; }
I don't understand the syntax but this seems possible. If so, how do I access it from an editor template?
If not, how could I dynamically send a SelectList to a DropDownList Editor Template? I specifically would like to avoid making a separate template for every SelectList - I have too many of them. Thanks
EDIT: I'm working on the second option (Reflection) because I thought it might be more direct than overriding that 15-syllable monster, the DataAnnotationsModelMetadataProvider.
You might want to take a look at this blog post:
http://mikevdm.com/BlogEntry/Key/Using-UIHint-With-ControlParameters-in-MVC
Here's a relevant quote:
ControlParameters are limited in that they can only accept (compile-time) constant values, in a somewhat unusual syntax, but they do allow simple vales (true/false, enumerated values, etc.), so your templated helper can behave slightly differently based on parameters. This allows you to combine related functionality, usually found in individual templates (with lots of code duplication), into one single template.
In my app, all my drop down lists were either nullable bools (Yes, No, not set) or enums. I took the route of making a separate template for each one, but using helper methods to make the code within each template very minimal.
For example, I have a template called Level (where Level is an enum):
The code is just a couple usings plus....
#Html.DropDownListFor(model => model, Model.ToSelectList<Level>())
I use these extension methods for ToSelectList:
public static SelectList ToSelectList<TEnum>(this TEnum? value) where TEnum : struct
{
var items = GetSelectListItems<TEnum>().ToList();
items.Insert(0, new SelectListItem { Value = "", Text = LabelIfNull });
return new SelectList(items, "Value", "Text", value.ToString());
}
public static SelectList ToSelectList<TEnum>(this TEnum value)
{
var items = GetSelectListItems<TEnum>();
return new SelectList(items, "Value", "Text", value.ToString());
}
public static IEnumerable<SelectListItem> GetSelectListItems<TEnum>()
{
var values = System.Enum.GetNames(typeof(TEnum));
return values.Select(v => new SelectListItem { Value = v, Text = v.ToFriendlyName() });
}
public static SelectList ToSelectList(this bool isTrue)
{
var items = new[]
{
new SelectListItem { Value = "true", Text = LabelIfTrue },
new SelectListItem { Value = "false", Text = LabelIfFalse }
};
return new SelectList(items, "Value", "Text", isTrue.ToString());
}
public static SelectList ToSelectList(this bool? isTrue)
{
var items = new[]
{
new SelectListItem { Value = string.Empty, Text = LabelIfNull },
new SelectListItem { Value = "true", Text = LabelIfTrue },
new SelectListItem { Value = "false", Text = LabelIfFalse }
};
return new SelectList(items, "Value", "Text", !isTrue.HasValue ? string.Empty : isTrue.Value.ToString());
}
Perhaps you could use control parameters to get down to a single template, but you'll definitely need to write your own DataAnnotationsModelMetadataProvider, as indicated in the blog post.

Resources