For my project I used web service for fetch data from database. getAvailableList() method is available in that service and it returns int[] array. I want to convert this into object and want to pass it into View.
below is Action method.
public ActionResult Ataxi()
{
var alist = IM.getAvailableList();
return View(alist);
}
this is my View
#model List<WEB1.Models.sub_employee>
#foreach(var item in Model){
if (item.SE_ID != null)
{
#Html.DisplayFor(modelItem => item.SE_ID)
}
}
I got error message of The model item passed into the dictionary is of type 'System.Int32[]', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[WEB1.Models.sub_employee]'. how do I overcome this problem?
Your view is strongly typed with WEB1.Models.sub_employee object so you can not pass int[] to your view that is what the compiler complaining about. if
IM.getAvailableList() method returns all sub_employee.SE_ID as a int[] and SE_ID is int32 then you can construct the sub_employee list like below and pass it. using the System.Linq Namespace.
var alist = IM.getAvailableList();
return View(alist.Select(x => new WEB1.Models.sub_employee { SE_ID = x }).ToList());
Check the return type of the method. It is not returning the list of employee. Its returning int. and as you are fetching the result in var alist, compiler is nor complaining about the data type but when you are passing it to your view as view is strongly typed hence it is complaining. Check wsdl document and find out the return type of the method.
Related
So currently, you can imagine I have 1 method that is the constructor that funcitons like
info.PersonalInfo=getPersonalInfo(Id);
info.MedicalInfo=getMedicalInfo(Id);
Thing is, all of those get data and get binarys are repeating 95% of the code
using (CVDataEntities data = new CVDataEntities())
{
var temp = data.PersonalInfo.Where(m => m.Id == Id).FirstOrDefault();
return temp;
}
The only thing that changes is instead of PersonalInfo its MedicalInfo.
I thought of using a switch and just sending a number as the selector for which specific object I would want.
But the problem is the method is made so that it can only return
public IEnumerable<PersonalInfo> getPersonalInfo (string Id)
Is there any way for me to make a IEnumerable that lets me return any object, or is there a better way to go about this. I want to do it mostly to reduce the code from 400 lines down to 200 at most.
Try using generic methods, you will be able to specify the return type of your function when you call it. This could make your code look like this :
public IEnumerable<T> getInfo<T>(string id)
{
// Some code
}
// Calling the function
info.PersonalInfo = getInfo<PersonalInfo>(Id);
info.MedicalInfo = getInfo<MedicalInfo>(Id);
But be careful while using it, cause the compiler won't know what type T is (it is only defined at runtime) so it could lead to some errors while processing the data (like missing properties / methods exclusive to a specific type)
EDIT : Johnathan Barclay made a good point by commenting that the // some code bit is relevant and asked "How would the correct property be selected on data? How do you access an Id property on T?"
To get the correct property and access an Id property, you could use System.Reflection and add a string parameter to get the name of the property you want to use, and another to give the Id property name to the function:
public IEnumerable<T> getInfo<T>(string id, string propertyToReadName, string propertyToCompareName)
{
using (CVDataEntities data = new CVDataEntities())
{
// Getting the enumerable not filtered first
IEnumerable<T> unfilteredList = (IEnumerable<T>)data.GetType() // Get the type
.GetProperty(propertyToReadName, typeof(T)) // Get the property (PersonalInfo or MedicalInfo)
.GetValue(data); // Get the value of this property in the `data` instance
// Filtering the list
IEnumerable<T> filteredList = unfilteredList.Where(m =>
typeof(T).GetProperty(propertyToCompareName) // Get the "id" property using parameter
.GetValue(m) // Get the "id" value of m instance
.Equals(id)); // Check if it equals the id given as parameter
return filteredList;
}
}
// Calling the function
info.PersonalInfo = getInfo<PersonalInfo>(Id, "PersonalInfo", "Id");
info.MedicalInfo = getInfo<MedicalInfo>(Id, "MedicalInfo", "Id");
If you want to return a single element instead of an IEnumerable don't forget to change the return type of the function from IEnumerable<T> to T and add .FirstOrDefault() at the return line
Note that you could also give another value to the parameter propertyToCompareName and make a comparison to another property of the T class
I have a model that has a PersonId int, and also, a List<SelectListItems> People for people. The UI allows me to select a person from the drop down model, and save the value into PersonId.
That works, but if there is an error in my ModelState, caused by another field, I do this:
if (ModelState.IsValid == false)
{
return View(model);
}
Problem is, the object holding the list of people is NULL in the returned model. Do I really need to repopulate it from the database again, or can this somehow be 'stored', and only populated when I initially create the view?
Yes. You need to load the SelectView again.
Only values in your inputs are posted (hidden or normal ones)... so anything to be posted must be in those inputs.
If you want to avoid going to the database... you should cache that list.
Here you can see an example for the caching logic: https://stackoverflow.com/a/349111/7720
Yes, you need to repopulate it. Only the selected value of a dropdown list is sent via a form. It's perfectly normal to do this. In general, if you have data available on the server, it always makes sense to cache it/query for it again, rather than trusting any input from a user.
To conveniently build SelectLists, rather than using SelectListItem, I use a method on a base controller:
[NonAction]
public SelectList BuildSelectList<TSource>(IEnumerable<TSource> source,
Expression<Func<TSource, int>> valueKey, Expression<Func<TSource, string>> textKey,
object selectedValue = null)
{
var selectedValueKey = ((MemberExpression)(MemberExpression)valueKey.Body).Member.Name;
var selectedTextKey = ((MemberExpression)(MemberExpression)textKey.Body).Member.Name;
return new SelectList(source, selectedValueKey, selectedTextKey, selectedValue);
}
Note the use of NonActionAttribute, which is used to indicate that a public controller method is not an action method.
Then in the controller, it's easy to build any list again, without polluting the actions too much. For example:
[HttpPost]
public ActionResult Index(SomeViewModel model)
{
if (ModelState.IsValid)
return RedirectToAction("Success");
// The model wasn't valid, so repopulate the dropdown
model.People = BuildSelectList(db.People, m => m.Id,
m => m.Name, model.PersonId);
return View(model);
}
You could do something similar for SelectListItem, rather than manually rebuilding your lists each time.
I have a view that displays a table of data that I want to be able to sort by specifying a property on the row type.
My model (so far) is:
class Model
{
List<DataType> data;
Expression<Func<DataType, object>> SortProperty;
}
I've tried creating that in the view to be passed into my controller as follows:
<a href='<%= Url.Action("Index", "Approvals", new IndexModel() { Page = Model.Page, SortProperty = ((ApprovalModel m) => m.Id)}) %>'>Id</a>
which renders as:
<a href='/PartsLegislation/Approvals.aspx/Approvals?SortProperty=m%20%3D%3E%20Convert(m.Id)'>Id</a>
so it sort of looks like it'll work (all-be-it with a Convert expression in there), however in the controller SortProperty is always null.
TL;DR: How can I pass an expression pointing to a property from my view to the controller?
Edit: My controller action is as below:
[HttpGet]
public ActionResult Index(Model viewModel)
{
....
viewModel.Approvals = PartsDC.Repository<Approval>()
.Where(a => !a.Deleted)
.OrderBy(viewModel.SortExpression)
.Skip((viewModel.Page ?? 0) * RowsPerPage)
.Take(RowsPerPage)
.Select(a => Mapper.Map<Approval, ApprovalHeaderModel>(a))
.ToList();
...
}
As far as I know you can't pass complex objects via URL. You can pass for example string with name of property.
However if you want to just sort table maybe you should think about another approach to this problem. Check this http://www.kryogenix.org/code/browser/sorttable/ .
It allows you to simply sort your table by clicking on headers.
The goal
I want to display in my view the results of stored procedure.
The problem
Entity Framework automatically imported for me a method that executes a procedure, however I'm not getting the results I expect displaying on the screen.
The imported function is:
public virtual ObjectResult<getProductsListForHome_Result> getProductsListForHome(Nullable<int> inOffer, Nullable<int> categoryId)
{
var inOfferParameter = inOffer.HasValue ?
new ObjectParameter("inOffer", inOffer) :
new ObjectParameter("inOffer", typeof(int));
var categoryIdParameter = categoryId.HasValue ?
new ObjectParameter("categoryId", categoryId) :
new ObjectParameter("categoryId", typeof(int));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<getProductsListForHome_Result>("getProductsListForHome", inOfferParameter, categoryIdParameter);
}
What I have already tried
On ProductsController:
//
// GET: /Products/
public ActionResult Index()
{
ObjectResult<getProductsListForHome_Result> products = db.getProductsListForHome(1, 14);
return View(products.ToList());
}
Using the previous code, when I access http://myapp.com/Products/ I'm getting the following message:
The model item passed into the dictionary is of type
'System.Collections.Generic.List1[MyApp.Models.getProductsListForHome_Result]',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable1[MyApp.Models.bm_products]'.
What do I have to do to resolve this?
First, well-written question!
This is a type-casting problem, and it looks like your answer is the accepted answer here:
MVC: The model item passed into the dictionary is of type X, but this dictionary requires a model item of type X
Most likely your View is a strongly typed one, and it is declared as
#model System.Collections.Generic.IEnumerable<MyApp.Models.bm_products>
However you are passing it a different type in controller, and experiencing the error.
What you can do:
Specify another type for the View. View itself might require some refactoring after this:
#model System.Collections.Generic.IEnumerable<MyApp.Models.getProductsListForHome_Result>
Preferable. Run some code in controller to convert collection returned from SP into something View can consume:
public ActionResult Index()
{
ObjectResult<getProductsListForHome_Result> products = db.getProductsListForHome(1, 14);
List<bm_products> viewProducts = products.Select(p => new bm_products{ProductName = p.Name, ProductPrice = p.Price}).ToList();
return View(viewProducts);
}
I'm somewhat new to the ASP.NET MVC architecture and I'm trying to sort out how I could return multiple sets of data to the view.
public ActionResult Index(string SortBy)
{
var actions = from a in dbActions.Actions
orderby a.action_name
ascending
select a;
return View(actions.ToList());
}
This code works very well for returning a single dataset. The situation I have is a that I've got a list of objects, each of which has a subset of objects that I want to display in a hierarchy on the output page. I'm not sure whether I'm looking for the quick way or the right way, thoughts on both avenues would be very much appreciated.
Thanks!
You could pass them through ViewData, an object that is passed from the controller to the view. The controller would look like this:
ViewData["ActionList"] = actions.ToList();
Retrieving it in the view:
<% foreach (var action in (List)ViewData["ActionList"]) %>
ViewData as described above is the quick way. But I beleieve it makes more sense to wrap the lists in a single object model which you then pass to the View. You will also get intellisense...
That subset of objects could/should be returned by a property on the Action (assuming db.Actions returns Action objects).
public class Action
{
//...
public IEnumerable<SubAction> SubActions
{
get { return do-what-ever; }
}
//...
}
Nothing special MVC'ish here...
In your view you just loop through both:
<%
foreach (Action a in ViewData.Model as IList<Action>)
{
foreach (SubAction sa in a.SubActions)
{
// do whatever
}
}
%>