Sorting of IEnumerable<T> in MVC 2 - c#

My Service layer returns a IEnumerable<ResortsView> to my Controller and I have to provide an option to SORT the results on UI by following criteria: Price (Excluding ZERO Price Items), SupplierName & Rating. Here is the code snippet of my objects/classes:
[Serializable]
public class ResortsView : SupplierView
{
public IList<ProductView> ResortProducts { get; set; }
public string CheckInTime { get; set; }
public string CheckOutTime { get; set; }
public virtual IList<ImageView> Images { get; set; }
}
[Serializable]
public class SupplierView
{
public string SupplierID { get; set; }
public string SupplierName { get; set; }
public string Description { get; set; }
public string Rating { get; set; }
public string URL { get; set; }
}
[Serializable]
public class ProductView
{
public string Code { get; set; }
public string Description { get; set; }
public decimal? Price { get; set; }
public ErrorView PricingError { get; set; }
}
What is the best way to handle sorting of results inside IEnumerable<ResortsView>?

Use the OrderBy method of the LINQ stack:
IEnumerable<ResortsView> source = GetResorts();
var model = source.OrderBy(rv => rv.CheckInTime);
To order by the lowest, non-zero price in ResortProducts:
var model = source.OrderBy(rv => rv.ResortProducts.Where(p => p.Price > 0).Min(p => p.Price));

Most likely if you'll want to use the Dynamic LINQ library, here are some instructions and a download link.
You'll need to have your action accept some sorting parameters:
public ActionResult MyAction(string sortField)
{
return View(myService.MyData().OrderBy(sortField));
}

Related

Cannot convert type IEnumerable to List C#

I'm trying to bring a listing to frontEnd.
I'm using mongoDb. My mongodb has a colletion called Employee. Employee has the following attribute
public class EmployeeViewModel
{
[BsonId(IdGenerator = typeof(StringObjectIdGenerator))]
public string ownerId { get; set; }
public string atributeChange { get; set; }
public PersonalDataViewModel personalData { get; set; }
public AddressViewModel address { get; set; }
public List<EmailsViewModel> emails { get; set; }
public SyndicateViewModel syndicate { get; set; }
public List<DependentsViewModel> dependents { get; set; }
public List<PhoneViewModel> phone { get; set; }
public List<BankViewModel> bank { get; set; }
public AttributesViewModel attributes { get; set; }
public List<BenefitsViewModel> benefits { get; set; }
public TransportViewModel transport { get; set; }
public List<AttachmentsViewModel> attachments { get; set; }
public List<DocumentsViewModel> documents { get; set; }
public List<DocumentsImagesViewModel> DependentsDocuments { get; set; }
public List<AttachmentsViewModel> DependentsAttachments { get; set; }
public List<BenefitsViewModel> DependentsBenefits { get; set; }
}
In this Model, I have an attribute called: public List <DocumentsImagesViewModel> DependentsDocuments {get; set; }:
public class DocumentsViewModel
{
[BsonId]
public string ownerId { get; set; }
public string id { get; set; }
public string dependentId { get; set; }
public string number { get; set; }
public DateTime expiration { get; set; }
public List<DocumentsImagesViewModel> images { get; set; }
public List<DocumentPropertiesViewModel> properties { get; set; }
public DocumentTypeViewModel type { get; set; }
}
I'm trying to bring benefits that contain the depedentID equal of the parameter. When I use this method, it has an error that can not be converted. IEnumerable to List C #
public async Task<List<Documents>> GetDocument(string ownerId, string dependentId)
{
var query = from employee in _employee.AsQueryable()
where employee.ownerId == ownerId
select new Employee()
{
DependentsDocuments = employee.DependentsDocuments.Where(x => x.dependentId == dependentId)
};
return query.ToList();
}
What is the best way to get this data? this filter?
I used this question as a reference: Mongodb C# driver return only matching sub documents in array
LINQ's .Where returns IEnumerable<T>, your model expects a List<T>, you can either change your model to IEnumerable<T> or you can change this line of code:
DependentsDocuments = employee.DependentsDocuments
.Where(x => x.dependentId == dependentId)
to this:
DependentsDocuments = employee.DependentsDocuments
.Where(x => x.dependentId == dependentId)
.ToList()
changing your code to this one maybe it work:
public async Task<List<Documents>> GetDocument(string ownerId, string dependentId)
{
var query = (from employee in _employee.AsQueryable()
where employee.ownerId == ownerId
select new Employee()
{
DependentsDocuments = employee.DependentsDocuments.Where(x => x.dependentId == dependentId).ToList()
}).ToList();
return query.ToList();
}

Linq query to get value from nested object

I need to pull a specific value from a nested object without using a foreach loop. I think the right approach here is a linq query, but I'm unable to grab the value I need. Considering the class structure:
public class Order
{
public int OrderID { get; set; }
public List<OrderItems> { get; set; }
}
public class OrderItems
{
public int OrderItemID { get; set; }
public string ItemName { get; set; }
public int Quantity { get; set; }
public List<OrderItemShipping> OrderItemShippings { get; set; }
}
public class OrderItemShipping
{
public int OrderItemShippingID { get; set; }
public Address ShipAddress { get; set; }
public class Address
{
public int AddressID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
I want to be able to do something like:
var shipToAddress = Order.OrderItems.OrderItemShipping.FirstOrDefault(x => x.Address.Address1);
But my syntax must not be correct, because I'm unable to grab the value I need?
If you need to access items of (nested) collections SelectMany is your friend:
var shipToAddress = Order.OrderItems
.SelectMany(oi => oi.OrderItemShipping.Select(ois => ois.ShipAddress.Address1)))
.FirstOrDefault();
Your syntax was wrong because the overload of FirstOrDefault expects a predicate(so a function that returns a bool) but you were passing: FirstOrDefault(x => x.Address.Address1).
If you need to filter it somehow("specific value from a nested object") you need to explain your requirement more precisely.

MVC Model doesnt support ToPagedList

I have a model like this
public class SearchVM
{
[DisplayName("Type")]
public string Type { get; set; }
[DisplayName("Beds")]
public string NumberOfBeds { get; set; }
[DisplayName("Baths")]
public string NumberOfBaths { get; set; }
[DisplayName("Prices From")]
public string PriceFrom { get; set; }
[DisplayName("Prices To")]
public string PriceTo { get; set; }
public IEnumerable<Rental> Rentals { get; set; }
public IEnumerable<Sale> Sales { get; set; }
public IEnumerable<Rental> FeatureRentals { get; set; }
public IEnumerable<Sale> FeatureSales { get; set; }
public Rental NewRentals { get; set; }
public Sale NewSales { get; set; }
}
In my controller when trying to use this model SearchVM i cannot use the ToPagedList method
public ActionResult Search(SearchVM searchvm, int page = 1)
{
var query = from c in context.Rentals
select c;
searchvm.Rentals = query;
return View("RentProperty", query.ToPagedList(page,9));
}
I noticed that searchvm.ToPagedList doesnt work. Can some one please help
You are either missing a library reference in your code or if you already have that, you need to add a relevant using statement. For example, you may need this at the top of your code:
using PagedList;
Without this line, the compiler doesn't know where to get the ToPagedList() extension method.

how to access Javascript multidimensional array in MVC controller

I have to pass array of filters like this:
Script Code:
return { CustomFilter: options.filter.filters };
++++++++++++++++++++++++++++++++++++++++++++++++
From Firebug:
CustomFilter[0][field] ItemName
CustomFilter[0][operator] startswith
CustomFilter[0][value] testing Value
CustomFilter[1][field] BrandName
CustomFilter[1][operator] startswith
CustomFilter[1][value] testing Value 1
Posted values are:
But i am unable to received these on Controller side.
i tried like this:
public ActionResult ReadOperation( string[][] CustomFilter)
Also like this:
public ActionResult ReadOperation( Filter[] CustomFilter)
public class Filter
{
public string field { get; set; }
public string #operator { get; set; }
public string value { get; set; }
}
But didn't work. Please Suggest.
Thank you.
Solution Found with Json deserialization
Script code changed to:
return { CustomFilter: JSON.stringify(CustomFilter) };
Controller Code changed to:
using Newtonsoft.Json;
public ActionResult ReadOperation(MyViewModel model)
{
var filters = JsonConvert.DeserializeObject(model.CustomFilter, typeof(CustomFilter[]));
}
public class MyViewModel
{
public string Filter { get; set; }
public string group { get; set; }
public int page { get; set; }
public int pageSize { get; set; }
public int sort { get; set; }
}
public class CustomFilter
{
public string field { get; set; }
public string #operator { get; set; }
public string value { get; set; }
}
Result View in controller:
It looks like an error with model structure.
public class MyViewModel
{
public Filter[] CustomFilter { get; set; }
public string Filter { get; set; }
public string Group { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int Sort { get; set; }
}
Try to use this type for model binding.
public ActionResult ReadOperation(MyViewModel model)
If you are using ASP.NET MVC 4, and cannot change the parameter names, maybe you can define a custom model in this way:
public class MyViewModel
{
public Dictionary<string,string>[] CustomerFilter { get; set; }
public string filter { get; set; }
public string group { get; set; }
public int page { get; set; }
public int pageSize { get; set; }
public int sort { get; set; }
}
Then, at the controller:
public ActionResult ReadOperation(MyViewModel model){ ... }
It seems that the notation used in the parameters generated by your grid is for dictionaries. Haven't tried a collection of Dictionaries, though.
In the post, try to send the data as this:
CustomFilter[0].Field ItemName
CustomFilter[0].Operator startswith
CustomFilter[0].Value testing Value
CustomFilter[1].Field BrandName
CustomFilter[1].Operator startswith
CustomFilter[1].Value testing Value 1
And at the controller:
public ActionResult ReadOperation(Filter[] CustomFilter)
Having a Filter class defined as:
public class Filter
{
public string Field { set; get; }
public string Operator { set; get; }
public string Value { set; get; }
}
(Be careful with the capital letters).
Or if you want to use the model approach, as Ufuk suggests, and having the same Filter class:
Model:
public class MyViewModel
{
public Filter[] CustomerFilter { get; set; }
public string Filter { get; set; }
public string Group { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int Sort { get; set; }
}
Parameters in POST:
CustomFilter[0].Field ItemName
CustomFilter[0].Operator startswith
CustomFilter[0].Value testing Value
CustomFilter[1].Field BrandName
CustomFilter[1].Operator startswith
CustomFilter[1].Value testing Value 1
Filter ItemName~startswith~'12'~and~BrandName~startswith~'123'
Group
Page 1
PageSize 15
Sort
Controller
public ActionResult ReadOperation(MyViewModel model)
See this link: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

Strongly Typed List.GroupBy()

I've been trying to find an answer to this on google and on SO
but everywhere I have found uses anonymously typed result lists
what I am trying to acheive is to take a List<SecondaryStandard>
and create a grouped List of SecondaryStandard
each SecondaryStandard looks like this
public class SecondaryStandard
{
public string Id { get; set; }
public int IdNumeric { get; set; }
public string IdText { get; set; }
public Sample Sample { get; set; }
public string StandardName { get; set; }
public DateTime DateCompleted { get; set; }
public SamplePoint SamplingPoint{ get; set; }
public Instrument Instrument{ get; set; }
public string ContainerId { get; set; }
public double Value { get; set; }
public string ComponentName { get; set; }
public string PointLocation { get; set; }
public string Description { get; set; }
public string Description2 { get; set; }
public string Analysis { get; set; }
public string Units { get; set; }
}
what i want is a List() where the Value Property is an average of results for each ComponentName.
Any ideas on how I could achieve this in a strongly typed way or do I need to suck it up and use anonymous objects to achieve what I'm looking for?
You mean this?
List<SecondaryStandard> list = new List<SecondaryStandard>();
// populate list
List<SecondaryStandard> result = list
.GroupBy(l => l.ComponentName)
.Select(s => new SecondaryStandard() { ComponentName = s.Key, Value = s.Average(x => x.Value) }).ToList();

Categories