I've done a GroupBy using Linq as follows in a controller:
model.aLstProducts = result[0].Results
.Where(c => c.Id == ProductId)
.ToList()
.FirstOrDefault()
.ListOfProducts
.GroupBy(c => c.ProductCategory);
The property has been defined as follows:
public IEnumerable<IGrouping<string, ProductsViewModel>> aLstProducts { get; set; }
When I try to use it in the front-end using Razor, it throws the following exception:
#foreach (var item in Model.aLstProducts)
{
}
Error:
The type 'IGrouping<,>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
What could be the reason for the above or how can I overcome it?
N.B: I can work with generic List in the Razor view but for the GroupBy getting the exception.
At the beginning of razor page add
#model IEnumerable<IEnumerable<IGrouping<string, ProductsViewModel>>
then loop through the Model
#foreach (var item in Model)
{
// your code goes here
}
use System.Linq at razor as well.
ms doc
Related
I am trying to build filter as below
Builders<Documents>.Filter.Where(x => filterJsonObj.HeaderFilterCreatedByList.Contains(EncryptHelper.DecryptText(x.CreatedBy)));
but it is throwing error at runtime
Unsupported filter: Contains(value(System.String[])).
But for below mentioned Filter it is working properly only diff in below filter query is in that I am not using any additional method.
Builders<Documents>.Filter.Where(x => filterJsonObj.DocumentTypes.Contains(x.Status));
Details of the method which I am using to decrypt is as below
public static string DecryptText(string decryptedValue)
{
if (String.IsNullOrWhiteSpace(decryptedValue)) return decryptedValue;
var values = decryptedValue.Split(",");
var decryptedValues = new List<string>();
foreach (var v in values)
{
decryptedValues.Add(String.IsNullOrWhiteSpace(v) ? v : EncryptDecrypt(v));
}
return String.Join(",", decryptedValues);
}
This one I have handled using below code
string[] createdByList = filterJsonObj.HeaderFilterCreatedByList.Select(x => EncryptHelper.EncryptText(x)).ToArray();
fil &= Builders<Documents>.Filter.In(x => x.CreatedBy, createdByList);
Instead of using Decryption method in the Filter first I have encrypted the list then used the same in Filter.
Any suggestions in the same are acceptable.
For some reason Additional method won't work because I tried to use StringComparer.CurrentCultureIgnoreCase and it showed error - Unsupported filter: value(System.String[]).Contains({document}{JobTitle}, value(System.CultureAwareComparer)).
If you want to refine your list you can do it after applying other filters and then on that filtered list you will be able to use the filter with additional method.
For Eg: var listData = filteredList.Where( ArrayOfString.Contains("Value", StringComparer.CurrentCultureIgnoreCase)).ToList();
Hope that works for you !
I have this working code:
#{
var ekgList = AsList(App.Data["Ekgs"]);
foreach(var ekg in ekgList) {
<div>
#foreach (var entitiesFromSinusDataType in ekg.Sinus) {
if(entitiesFromSinusDataType.EntityId == Content.EntityId) {
<a>#ekg.ShortName</a>
}
}
</div>
}
}
For what I can understand:
ekgList is a list (standard 2sxc code for accessing data)
ekg.Sinus is a field in Ekgs content type (Entity data type, multiple, which creates a list of entities from another content type,
Sinus)
Content.EntityId is an int, the same as entitiesFromSinusDataType.EntityId
There should be an easy way to remove the second loop and the "if", by placing a where clause in the first loop.
I'm trying this step by step, but as soon as I try this:
#{
var ekgList = AsList(App.Data["Ekgs"]);
foreach(var ekg in ekgList) {
<div>
#foreach (var entitiesFromSinusDataType in ekg.Sinus.Where(i => i.EntityId == Content.EntityId)) {
<a>#ekg.ShortName</a>
}
</div>
}
}
I get this error:
CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type
This seems to be caused by using dynamic types.
Is there some way to cast the lists into a non dynamic version of them?
Try to cast the ekg.Sinus to ((IEnumerable<dynamic>)ekg.Sinus) :
((IEnumerable<dynamic>)ekg.Sinus).Where(i => i.EntityId == Content.EntityId)
I hope this will help you out.
This is because the compiler cannot guess that ekg.Sinus is a list - so LINQ extensions are not automatically resolved. Note that you can also do this since 2sxc 10.25:
AsList(ekg.Sinus).Where(...)
or in case that doesn't work (again sometimes the compiler can't guess everything) do:
AsList(ekg.Sinus as object).Where(...)
I also suggest you check out the LINQ tutorials https://2sxc.org/dnn-tutorials/en/razor/linq/home
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.
I am using a lambda expression to fetch two column in a table but how can i access this in my view using viewbag, and what will be the type if we fetch two columns from a table using lambda expression.
Ex:
GatesEntities Gates = new GatesEntities();
ViewBag.Index = Gates.Concepts.OrderBy(s => s.concept_id).Select(s => new { s.Concept_Name,s.Session_Id });
return View();
I have 5 sessions, in each session i have some concepts. Now I need to fetch concept names for each session in my view using viewbag.
Please help me with this, I wasted lot of time on this..
GatesEntities Gates = new GatesEntities();
ViewBag.Index = Gates.Concepts.OrderBy(s => s.concept_id).ToList();
return View();
View code
#foreach(var c in (List<Concepts>)ViewBag.Index)
{
#c.Concept_Name
}
The syntax of new { ... } means you're creating what's referred to as an "anonymous object". These are typed as object and require that you reference the properties inside "dynamically", which is to say at runtime.
As a result, it's a really bad idea to use this for things like views, where you're only getting runtime compilation to begin with. At least in something like a controller action, you'll get a bit of compile-time error checking, but in views this is just a time-bomb waiting to explode.
Classes are cheap, and if you're going to do something like this is far preferable to create a class to hold the values as then you'll be strongly-type the whole way through. That means less errors as Visual Studio will properly scream at you as you're writing the code and compile-time errors if you make a mistake anyways. For example (guessing at your types here):
public class ConceptViewModel
{
public string Concept_Name { get; set; }
public Guid Session_Id { get; set; }
}
Then:
var model = Gates.Concepts.OrderBy(s => s.concept_id).Select(s => new ConceptViewModel {
Concept_Name = s.Concept_Name,
Session_Id = s.Session_Id
});
return View(model);
And finally in your view:
#model IEnumerable<ConceptViewModel>
// whatever
Viewbag.Index is an IEnumerable(because Gates.Concepts.OrderBy(s => s.concept_id).Select(s => new { s.Concept_Name,s.Session_Id }) returns a collection), so iterate over it on the view.
#foreach(Concept i in (IEnumerable<Concept>)Viewbag.Index){
<p>#i.Concept_Name</p>
<p>#i.Session_Id</p>
}
I have a ASP.NET MVC4 Application.
My view get a List from my controller.
I want to select these list with lambda expression but I get the following error:
Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type
List<project.Models.LAYER> layers = new List<project.Models.LAYER>();
layers = #Model.layers.Select(x => x.KONT == "EUROPE");
#Model.layers is a List
NOW I TRIED THAT: BUT THE SAME ERROR:
#{
List<project.Models.LAYER> layers = Model.layers.Where(x => x.KNOT == "EUROPE").ToList();
}
It looks like you're doing this in your view, which violates the principles of separation of concerns. But this is how you would do it.
#
{
var layers = Model.layers.Where(x => x.KONT == "EUROPE").ToList();
}
#foreach(var layer in layers)
{
.....
}
A Better Way
What you should do however is create a method on your Model "GetLayersForLocation" Then your code would look like this:
In Your Model Class
public IEnumerable<Layer> GetLayersForLocation(string location)
{
return this.layers.Where(x => x.Knot == location);
}
In Your View Code
#foreach(var layer in Model.GetLayersForLocation("EUROPE"))
{
.....
}
The reason this is better is you can now unit test your code, before you wouldn't be able to because it's just part of your view, but now you can run automated tests to ensure that getting the proper layers is working.
For others, I've notice I get this error in Views when I do not have a strongly typed view, such as if a single character accidentally gets typed before the "#model type" line (and thus the model type declaration is now no longer being made.)
#model SomeModel
layers is a List, Model.layers.Select will return an IEnumerable.
If you only want to return layer whose KONT == ‘EUROPE', you should use like following
layers = #Model.layers.Where(x => x.KNOT == "EUROPE").ToList();