I have a model passed from controller to view in my asp.net mvc5 website. Then I show the dropdownlist using the model and I want to pass an id back when submitting the form. Here is my model :
public class SiteDirectionModel
{
public int id { get; set; }
public string name { get; set; }
}
Then in the model, I use a List<SiteDirectionModel> to which I add new instances of each item I need. I fill up both these lists and then pass my model to the view.
#model List<SiteDirectionModel>
#using (Html.BeginForm("GetSiteRF", "Create", FormMethod.Post))
{
#Html.DropDownListFor(x => x.name,new SelectList(Model.name,"Sites"));
<input type="button" value="Selectionner" class="btn btn-primary"/>
}
Then how to retrieve the ids for each name ? And how to pass it as a parameter to my controller? Such that I would have :
public ActionResult GetSiteRF(int id)
{
int newId = id;
//Call method to searchId ...
return View("CreateADUser");
}
I have given how to bind and get value from dropdown. Please use your own BL in this.
Your model should be like this.
public class Something
{
public int Id { get; set; }
public string Name { get; set; }
}
public class SiteDirectionModel
{
public SelectList MyDropDown { get; set; }
public int SelectedValue { get; set; }
}
You BL should be like this.
public List<Something> GetListofSomething()
{
//your logic.
}
Your Get method should be like this.
public ActionResult MyGetMethod()
{
SiteDirectionModel model = new SiteDirectionModel();
model.MyDropDown = new SelectList(GetListofSomething(), "key_field_name", "value_field_name", "default_value");
}
Then finally HTML
#Html.DropDownListFor(x => x.SelectedValue,Model.MyDropDown)
Related
I've been searching all over the web to find an answer for such simple question, but I can't seem to find one.
Suppose we have a Product that has an edit page where we can set name, price and category.
Following the MVC(MVVM) pattern we have:
2 models ProductModel and ProductCategoryModel
ViewModel that holds the product and the categories list (for the dropdown)
View to display the edit page
Beside the above we have the ProductService which handles the CRUD operations
// Model
public class ProductModel
{
public int ProductId { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
}
// Model
public class ProductCategoryModel
{
public int CategoryId { get; set; }
public string Name { get; set; }
}
// ViewModel
public class EditProductViewModel
{
public ProductModel Product { get; set; }
public List<ProductCategoryModel> Categories { get; set; }
}
The question is who is responsible for populating the ViewModel? I though it could be done in the constructor of the view model, however people say it is bad practice. Populating it in the controller also doesn't seems right.
You will map your EditProductViewModel from your ProductModel/ProductCategoryModel in the page controller.
You can then call your action to render your html page and pass your viewModel object.
Something like this :
public class HomeController : Controller
{
private EditProductViewModel viewModel;
public HomeController()
{
this.viewModel = new EditProductViewModel();
InitialiseViewModel();
}
public ActionResult Index()
{
return View("Index", viewModel);
}
private void InitialiseViewModel()
{
ProductCategoryModel productCategoryModel = new ProductCategoryModel();
ProductModel productModel = new ProductModel();
//do your mapping
productModel.Name = "Test mapping";
this.viewModel.Product = productModel;
}
}
Your .cshtml will look like this
#model WebApplication5.ViewModels.EditProductViewModel
<div class="jumbotron">
<h1>ASP.NET</h1>
<p>#Model.Product.Name</p>
<p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p>Learn more ยป</p>
</div>
I have a dormitory adding page and this dormitories can have features so I want to use CheckBox list for this.
There is a list of all features a dormitory can have.
public class DormFeatureModel
{
[Key]
public int FeatureID { get; set; }
public string FeatureName { get; set; }
public List<DormHasFeatureModel> DormHasFeature { get; set; }
}
Here, too, are features that a dormitory has.
public class DormHasFeatureModel
{
[Key]
public int HasFeatureID { get; set; }
[Required]
public int FeatureID { get; set; }
[Required]
public int DormID { get; set; }
public virtual DormModel Dorm { get; set; }
public virtual DormFeatureModel DormFeature { get; set; }
}
I can get features list in razor as checkbox
but I can't get selected checkboxes id list(so, FeatureID)
How can I get list in controller ?
First, add a ViewModel that correlates the Checked boolean with the FeatureId.
public class SelectedFeatureViewModel {
public bool Checked { get; set; } // to be set by user
public int FeatureID { get; set; } // to be populated by GET action
public string FeatureName { get; set; } // to be populated by GET action
}
The GET action creates the main ViewModel and initializes the list of available features (DormOptions).
public class CreateDormViewModel {
// used to render the checkboxes, to be initialized in GET controller action
// also used to bind the checked values back to the controller for POST action
public ICollection<SelectedFeatureViewModel> DormOptions { get; set; }
}
In the Razor markup, bind the checkboxes to the DormOptions collection:
#model CreateDormViewModel
#using (Html.BeginForm("CreateDorm", "DormAdministration", FormMethod.Post)) {
// use for loop so modelbinding to collection works
#for (var i = 0; i < Model.DormOptions.Count; i++) {
<label>#Model.DormOptions[i].FeatureName</label>
#Html.CheckBoxFor(m => m.DormOptions[i].Checked)
// also post back FeatureId so you can access it in the controller
#Html.HiddenFor(m => m.DormOptions[i].FeatureID)
// post back any additional properties that you need to access in the controller
// or need in order to redraw the view in an error case
#Html.HiddenFor(m => m.DormOptions[i].FeatureName)
}
}
In the CreateDorm POST action, the checkbox values are bound to the ViewModel property you gave in the CheckBoxFor lambda, i.e. the Checked property in the DormOptions collection.
[HttpPost]
public ActionResult CreateDorm(CreateDormViewModel postData) {
var selectedFeatureIds = new List<int>();
foreach (var option in postData.DormOptions) {
if (option.Checked) {
selectedFeatureIds.Add(option.FeatureID);
}
}
// ...
}
You can get the list by using the name of the checkboxes, let say your name of the checkboxes is chklstfeatureid then in controller you can get list like below
public actionresult createdorm(list<int> chklstfeatureid)
{
}
Thanks
I have a model that contains a List of Milestone, I want that list to be populated (inside the model) with a given set of Textboxes in the webpage.
public class Project
{
public string ProjectNumber { get; set; }
public IList<Parameter> Parameters;
public IList<Milestone> MilestoneList = new List<Milestone>();
}
And inside my Html.BeginForm("Edit", "Home", FormMethod.Post, new { Project = Model })) I have the following TextBox.
#for (int i = 0; i < Model.MilestoneList.Count; i++)
{
<td style="align-content: center;">#Html.TextBoxFor(model=>model.MilestoneList[i].Value)</td>
}
My problem in my controller below the milestonelist is always null in model Project
[HttpPost]
public ActionResult Edit(Project project)
{
helper.CreateProject(project, System.Web.HttpContext.Current.User.Identity.Name);
return View();
}
So how should I program so the list inside the model will be populated through TextBoxes?
Your using fields in the model, not properties, so the DefaultModelBinder cannot set the value. Change you model to
public class Project
{
public string ProjectNumber { get; set; }
public IList<Parameter> Parameters { get; set; }
public IList<Milestone> MilestoneList { get; set; }
}
and initialize the collection in in the controller.
I am accessing Data in Controller using a WCF Service.
public ActionResult Index()
{
DataRerieveClient _proxy = new DataRerieveClient();
var orderDetails = _proxy.GetProductDetails(null);
return View();
}
Now how to pass the orderdetails from Controller to view and how to access them in View.
Edit:
I have a Model :
public class OrderDetails
{
public int OrderId { get; set; }
public int ProductId { get; set; }
public decimal UnitPrice { get; set; }
public int quanity { get; set; }
public decimal Discount { get; set; }
}
and _proxy.GetProductDetails(null) returns List<ServiceType.OrderDetails>
Do I need a Local Model at all in this scenario?
How do I display the List values in a table in my view?
Edit2:
public class AutoMapperConfig
{
public static void Configure()
{
Mapper.Map(ServiceOrders.OrderDetails, NorthWindMVCWCF.Models.OrderDetails);
}
}
Now getting the Error
'NorthWindMVCWCF.ServiceOrders.OrderDetails' is a 'type', which is not valid in the given context
'NorthWindMVCWCF.Models.OrderDetails' is a 'type', which is not valid in the given context
I prefer to create view models, I would do it as follows:
Create View Models
public class OrderDetailViewModel
{
public int OrderId { get; set; }
public int ProductId { get; set; }
public decimal UnitPrice { get; set; }
public int Quanity { get; set; }
public decimal Discount { get; set; }
}
public class OrderDetailsViewModel
{
public OrderDetailsViewModel()
{
OrderDetails = new List<OrderDetailsViewModel>();
}
public List<OrderDetailsViewModel> OrderDetails { get; set; }
}
Manual projection
You could create an OrderDetails view model and project an instance manually as follows:
var orderDetailsViewModel = new OrderDetailsViewModel();
foreach(var orderdetail in orderDetails)
{
orderDetailsViewModel.Add(new OrderDetailsViewModel { OrderId = orderDetail.OrderId, ProductId = orderDetail.ProductId, UnitPrice = orderDetail.UnitPrice, Quanity = orderDetail.quantity, Discount = orderDetail.Discount });
}
AutoMapper alternative projection
Install AutoMapper, run the following from the package manager console:
Install-Package AutoMapper
Create an AutoMapperConfig.cs in the App_Start folder with the mappings, similar to below:
public static class AutoMapperConfig
{
public static void Configure()
{
Mapper.CreateMap<OrderDetails, OrderDetailViewModel>();
}
}
In your global asax call the configure method:
protected void Application_Start()
{
...
AutoMapperConfig.Configure();
...
}
Then map in your controller:
var orderDetailsViewModel = new OrderDetailsViewModel();
orderDetailsViewModel.OrderDetails = Mapper.Map<List<OrderDetails>, List<OrderDetailsViewModel>>(orderDetails);
I prefer to use the AutoMapper approach as the mapping is defined globally and can be reused within your app.
Returning your view model
Your view model would then be passed back as follows:
return View(orderDetailsViewModel);
Razor output
You access it in your view by adding a model reference at the top:
#model OrderDetailsViewModel
Then output the properties as follows, I've only included OrderId but you can just add the fields the same way:
<table>
<tr>
<th>OrderId</th>
</tr>
#foreach(var orderDetail in Model.OrderDetails)
{
<tr>
<td>#orderDetail.OrderId</td>
</tr>
}
</table>
You have create ViewModel for that.
For example in your model folder create a class:
public class MyViewModel // Whatever name you want to give
{
//My fields which I want to pass to View
publis string Field1{get;set;}
etc
etc
}
public ActionResult Index()
{
DataRerieveClient _proxy = new DataRerieveClient();
var orderDetails = _proxy.GetProductDetails(null);
List<MyViewModel> viewModelList = new List<MyViewModel>();
foreach(var orderDetail in orderDetails)
{
MyViewModel viewModel = new MyViewModel(); //Create an object of your ViewModel
viewModel.Field1 = orderDetails.Field1; //set all feilds like that
viewModelList.Add(viewModel);
}
return View(viewModelList); // Pass View Model to View
}
Note: You have to create View for your ViewModel
Like
#model `List<MyViewModel>`
then use this ViewModel to access properties.
To know more about what is ViewModel, refer to the link below:
http://sampathloku.blogspot.ae/2012/10/how-to-use-viewmodel-with-aspnet-mvc.html
in the Controller class write :
public ActionResult Index()
{
DataRerieveClient _proxy = new DataRerieveClient();
var orderDetails = _proxy.GetProductDetails(null);
return View(orderDetails);
}
i assume your project name is MvcApplication2 and your class name is in Model Folder. so add follow code in top of View (sample.cshtml) :
#model MvcApplication2.Models.OrderDetail
ok , you can use this code to access properties of DataRecieveClient :
<div class="display-label">
#Html.DisplayNameFor(model => model.F1)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.F1)
</div>
Sorry for poor english.!
I have a class that requires another class to be specified, but I don't want the MVC ModelState validator to check whether the secondary model is valid. Is this possible?
Here's a brief overview:
My entities look something like this:
public class WidgetType
{
public long Id { get; private set; }
[Required]
public string Name { get; set; }
...
}
public class Widget
{
public long Id { get; private set; }
[Required]
public string Name { get; set; }
[Required]
public WidgetType WidgetType { get; set; }
...
}
I have them encapsulated in a WidgetViewModel class that I'm passing to/from the View like this:
public class WidgetViewModel
{
public Widget Widget { get; set; }
public ICollection<WidgetType> WidgetTypes
{
get
{
return _repository.GetWidgets();
}
}
...
}
My view looks something like this:
...
#Html.DropDownListFor( m => m.Widget.WidgetType.Id, new SelectList( new EquipmentViewModel().EquipmentTypes, "Id", "Name" ) )
...
All of this works except for validation. ModelState.IsValid is always false because "Widget.WidgetType.Name" is required. I need the user to select a WidgetType, but I don't want ModelState to be validated deeper than "Widget.WidgetType.Id" (which should be all that Widget needs for its foreign key?).
Is there a better way to do this? I feel like there should be some way to validate without recursively inspecting deeper into the properties, but I can't find it. What am I missing...?
public class WidgetViewModel
{
[Required]
public string Name { get; set; }
[Required]
public WidgetType WidgetTypeId { get; set; }
public SelectList WidgetTypes
{
get
{
//This should be popuplated in your controller or factory not in the view model
retun new SelectList{ _repository.GetWidgets(),"Id","Name");
}
}
}
In your view
#Html.DropDownListFor( m => m.WidgetTypeId, Model.WidgetTypes)
And in your controller
public ActionResult Create(WidgetViewModel model)
{
Widget widget = new Widget{
Name = model.Name,
WidgetType = yourManager.GetWidgetTypeByID(model.WigetTypeId);
};
yourManager.Create(widget);
//...
}
If all you need in your view is the WidgetID then you don't need to include the entire Widget in the WidgetViewModel. Just have property called WidgetID. View model classes should have only the data the is necessary for the view.
In the controller action method that is called when you submit the form, you can use the WidgetID to fetch the Widget object from the database if it is needed.
http://blog.stevensanderson.com/2010/02/19/partial-validation-in-aspnet-mvc-2/ gives an example of partial validation