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.!
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 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)
Okay, so i have my ViewModel and I understand what the controller does, I'm just having difficulty implementing it. I don't know how to code a controller for the ViewModel, i've tried researching it myself and can't find anything.
Here is my viewModel, how would I go about constructing the controller? Not asking you to do it for me, just how to do it
public class ViewOrderViewModel
{
//From ORDER Table
public int OrderId { get; set; }
public System.DateTime OrderDate { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Email { get; set; }
public decimal Total { get; set; }
//from Products
public List<Product> Products { get; set; }
}
UPDATE
public class ViewOrderController : Controller
{
// GET: ViewOrder
public ActionResult ViewOrders()
{
var order = new Order();
var viewModel = GetViewModel(order);
return View(viewModel);
}
public ViewOrderViewModel GetViewModel(Order orderObject)
{
ViewOrderViewModel viewModel = new ViewOrderViewModel();
viewModel.OrderId = orderObject.OrderId;
viewModel.OrderDate = orderObject.OrderDate;
viewModel.FirstName = orderObject.FirstName;
viewModel.LastName = orderObject.LastName;
viewModel.City = orderObject.City;
viewModel.Address = orderObject.Address;
viewModel.Country = orderObject.Country;
viewModel.Email = orderObject.Email;
viewModel.PostalCode = orderObject.PostalCode;
viewModel.Total = orderObject.Total;
return viewModel;
}
}
Still unsure about how to map the List of products in the ViewModel class to the list of products in the db
Typically, your view is going to be "bound" to the ViewModel. It's like saying "Ok, I'm the view for an 'Order' and I only need to worry about the properties that you defined in ViewOrderViewModel".
The controller is not required for that binding to happen. The binding is declared at the top of your view:
Order.cshtml
#Model MyProject.Web.ViewModels.ViewOrderViewModel
<div>
<!-- Html for the view-->
</div>
This allows you to access properties on that model within the view. Razor has some functions that make life easy. For example, if you want to display the OrderId it might look like this:
<span>OrderId: #Model.OrderId </span>
The view doesn't care what values are set for each of those properties, it only cares that the properties exist. Where the controller comes into play is populating those properties with the values you want and then passing the ViewModel to the view:
public ActionResult Order()
{
var viewModel = new ViewOrderViewModel();
// Load data into each property
viewModel.OrderId = 123; // etc..
// Return it to the view. Asp.net knows to return
// it to the Order.cshtml view because the view
// and the controller action share the same name.
return View(viewModel);
}
Edit: In response to your questions in the comments: If you need to populate your ViewModel with values from a different model (such as a database model) you can create a mapper like so:
public ViewOrderViewModel GetViewModel(Order orderObject)
{
ViewOrderViewModel viewModel = new ViewOrderViewModel();
viewModel.OrderId = orderObject.OrderId;
viewModel.FirstName = orderObject.FirstName;
// etc...
return viewModel;
}
and then in your controller you would do something like this:
// var order = new Order()
var viewModel = GetViewModel(order);
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.
Problem is: I want to run 3 different actions but instead of that i want to fed all data from single action in a bigger model.
I am using:
public class SearchScrapClass
{
public WClass WClass { get; set; }
public SClass SClass { get; set; }
public YClass YClass { get; set; }
}
public class WClass
{
public string title { get; set; }
public string link { get; set; }
}
public class SClass
{
public string title { get; set; }
public string link { get; set; }
}
public class YClass
{
public string title { get; set; }
public string link { get; set; }
}
I am using LINQ to add data in these models.
I am using :
var wikians = from info in document.DocumentNode.SelectNodes("//div[#id='span']")
from link in info.SelectNodes("div//a").Where(x => x.Attributes.Contains("href"))
select new SearchScrapClass //Main Bigger Class
{
WClass.link= link.Attributes["href"].Value, //ERROR: How to add to WClass's url ?
WClass.title= link.InnerText //ERROR: How to add to WClass's url ?
}
var wikians = from info in document.DocumentNode.SelectNodes("//div[#id='results']")
from link in info.SelectNodes("p//a").Where(x => x.Attributes.Contains("href"))
select new SearchScrapClass //Main Bigger Class
{
YClass.link= link.Attributes["href"].Value, //ERROR: How to add to YClass's url ?
YClass.title= link.InnerText //ERROR: How to add to YClass's url ?
}
//Also for the 3rd class (model)
return View(wikians); //and then return bigger class model so that i can access them in view
This is one way i want to add data to link and title of all the classes.
My try is to add data to all 3 classes from different sources and pass the bigger model to view so that i can access all the classes as:
#model SearchScrapClass
#using(Html.BeginForm()) {
#Html.EditorFor(o => o.WClass.link)
...
}
Please suggest a way
Thanks
To Expand on my comment, I would suggest creating a ViewModel folder for organization sake. in this add the view model
public class SearchScrapClassViewModel
{
SearchScrapClass searchScrap;
WClass wClass;
SClass sClass;
YClass yClass;
}
In your controller then you instantiate the new viewmodel
SearchScrapClassViewModel model = new SearchScrapClassViewModel
{
....add in your logic to fill your class objects here
}
return view(model);
then in your view add the using for the viewmodel.
#using SearchScrapClassViewModel
You can pass multiple model by creating a new model class which will contain multiple objects.
public class MultiModel
{
SearchScrapClass searchScrap;
WClass wClass;
SClass sClass;
YClass yClass;
}
See the tuple tutorial http://www.dotnetperls.com/tuple or this one http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx
Like controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var first = new FirstModel();
var second = new SecondModel();
return View(Tuple.Create(first,second));
}
}
And the view:
#model Tuple
<div>
#Model.Item1.FirstModelProp
#Model.Item2.SecondModelProp
</div>
SearchScrapClassViewModel model = new SearchScrapClassViewModel
{
....add in your logic to fill your class objects here
}
what logic we apply here " ....add in your logic to fill your class objects here"