loop through model in mvc razor code behind - asp.net-mvc

I am working on MVC4 App, and I am stuck at one point, I tried using google to help me, but without success. This might be more simple then I think, but coming from web forms and shifting to mvc is "painful" sometime.
I am trying to loop through the model I have and get the values stored in that model. I tried few approaches but I am getting an error everytime. This is what I have:
var modelAgentFilter = from s in _aa.Agents
where s.COUNTER == Convert.ToInt32(AgentID)
select s;
if (modelAgentFilter != null)
{
ViewBag.FirstName = // Get FirstName object here
}
Thanks in advance for your comments.
Laziale
EDIT:
I did include for loop like this:
if (modelAgentFilter != null)
{
foreach (var property in modelAgentFilter)
{
string test = property.ADDRESS;
}
}
But when the compiler will reach the foreach step I am getting this error: "LINQ to Entities does not recognize the method 'Int32 ToInt32(System.Object)' method, and this method cannot be translated into a store expression."
I can get to the properties of the var model using that foreach look but as soon as the compiler will try to loop the model that error pops up.
Thanks again

LINQ to Entities does not recognize any methods. You can't use even ToString() in LINQ expression. You need first convert your value and than add it in LINQ.
In your example you need to do something like following:
var _agentID = int.Parse(AgentID);
var modelAgentFilter = from s in _aa.Agents
where s.COUNTER == _agentID
select s;

Related

Problem creating an Entity object/queryable from the result of a LINQ join in MVC

I'm attempting to write a search function for a database table that needs to access information from related tables using Entity Framework. However, I'm running into problems getting the data back out of my initial query after doing a join on the parent table and the related tables. My code currently looks like this. I initialize my queryable object
IQueryable<PurchaseOrder> po = _context.PurchaseOrders;
Where PurchaseOrder is an Entity type. Then there is a series of blocks like this.
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
var helper = _context.PurchaseOrderComments.Where(x => x.CommentText.Contains(searchViewModel.Comment));
var mid = po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) =>
new
{
PurchaseOrderID = r.PurchaseOrderID,
PurchaseOrderNumber = r.PurchaseOrderNumber,
VendorID = r.VendorID,
ContractNumber = r.ContractNumber,
BuyerUserID = r.BuyerUserID
});
po = mid.Select(x => new PurchaseOrder
{
PurchaseOrderID = x.PurchaseOrderID,
PurchaseOrderNumber = x.PurchaseOrderNumber,
VendorID = x.VendorID,
ContractNumber = x.ContractNumber,
BuyerUserID = x.BuyerUserID
});
}
After each block, po is passed to the next search parameter. However, as you might guess, my program complains that I can't build a complex type in mid's Select statement. I've also tried building PurchaseOrder objects from the contents of mid, inserting them into a new List of PurchaseOrders, and converting that list into a queryable to assign to po to pass on to the next block. However, that changes po's data type from System.Data.Object.ObjectSet to System.Collections.Generic.List, which then throws an InvalidOperationException the next time I try and iterate through it using a foreach.
So my question is, are there any obvious mistakes in my approach or any suggestions for other ways to approach the problem? Thanks very much for any help.
I think you're making this more complicated than it needs to be. If I understand what you're trying to do, you should be able to do something like this:
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
po = po.Where(
o => o.PurchaseOrderComments.Any(
c => c.CommentText.Contains(searchViewModel.Comment)));
}
StriplingWarrior's solution is the best way. In case that your PurchaseOrder class really doesn't have a navigation collection of PurchaseOrderComments (which would force you to use a join) the following should work and is simpler as your double projection:
po=po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) => r);

Filter BindingSource with entity framework

Hi
How can i filter results exists in BindingSource filled with entities ( using EF 4)?
I tried this:
mybindingsource.Filter = "cityID = 1"
But it seems that binding source with entity framework doesn't support filtering .. am i right ?,is there another way to filter(search) data in binding source .
PS:
- I'm working on windows application not ASP.NET.
- I'm using list box to show the results.
Thanx
Maybe a better one than Leonid:
private BindingSource _bs;
private List<Entity> _list;
_list = context.Entities;
_bs.DataSource = _list;
Now when filtering is required:
_bs.DataSource = _list.Where<Entity>(e => e.cityID == 1).ToList<Entity>;
This way you keep the original list (which is retrieved once from the context) and then use this original list to query against in memory (without going back and forth to the database). This way you can perform all kinds of queries against your original list.
I think, you have made mistake in syntax. You should write Filter like this:
mybindingsource.Filter = "cityID = '1'"
Another way is to use LINQ expressions.
(About LINQ)
Why do you have to call Entety again?
Simple solution:
public List<object> bindingSource;
public IEnumerable FiltredSource
{
get{ return bindingSource.Where(c => c.cityID==1);
}
.where (Function (c) c.cityID = 1)

will asp.net mvc model binder keep a posted array in the proper order?

so i've got an array of numbers that i'm posting to an asp.net mvc action that has a list(of integer) parameter and it all works great.
my question is this:
Is it safe to assume that the list(of integer) will have the numbers in the same order as they were in the array i posted?
Thanks for your time!
EDIT:
The data being posted looks like this:
POSTDATA=model.LevelIds=6&model.LevelIds=19&model.LevelIds=16&model.LevelIds=21&model.LevelIds=18
I'm using the Tamper Data firefox add on to see it.
I'm using jQuery, in traditional mode.
EDIT:
the action looks something like this:
public function Create(byval model as thecreateviewmodel) as actionresult
the thecreatviewmodel has a bunch of properties, but the interesting one is...
Public Property LevelIdsAs IList(Of Integer) = New List(Of Integer)
on the client side the view model is build with javascript/jquery:
function NewEntityDataBuilder() {
var theData = {
'model.Name' : $('#Name').val(),
'model.Description' : $('#Description').val(),
'model.LevelIds' : $('#LevelIds').val()
};
return theData;
}
that function is called from this bit of javascript which basically goes through the and adds all of the things in the list to a drop down list (select control) and selects them all.
$('#LevelIds').empty();
$('#AddedLevels').children().each(function () {
$('#LevelIds').append("<option value='" + $(this).attr('LevelId') + "'>" + $(this).attr('LevelId') + "</option>");
});
$('#LevelIds').children().attr('selected', 'selected'); //select all the options so they get posted.
var dataToPost = NewEntityDataBuilder();
this seems fairly convoluted when it's put this way, but it's actually fairly simple. it's all part of 2 connected drag and drop lists that are part of a form.
so: if i put the value of a select list with all of it's options selected in a variable and post that to an ilist(of integer) will ilist have them in the same order as they were in the select. It SEEMS like they are. but is that just a coincidence?
Usually the index is part of the parameter name:
ints[0]=0&ints[2]=2&ints[1]=1
And if you have a controller action that looks like this:
public ActionResult Index(List<int> ints)
{
// ints[0] = 0
// ints[1] = 1
// ints[2] = 2
return View();
}
UPDATE:
Let's suppose that you have multiple parameters with the same name in the query string. This query string will be parsed by the ASP.NET engine by the native HttpRequest object be convert into a NameValueCollection and more precisely a custom implementation called HttpValueCollection. This class is internal to ASP.NET which means that it is not documented and it might change with versions of .NET. Looking at it with Reflector there is the FillFromString and the way it is implemented it seems to preserve the order. But this is something I wouldn't rely on.

ADO.Net Entity Framework/Linq

I'm look at learning a bit more ASP.Net MVC and Linq To Entity.
I'm working on a project using this and am having a problem with the following line of code
ViewData["ProjectName"] = db.Projects.FirstOrDefault(p => p.ProjectId == task.ProjectId).ProjectName;
It works fine when the record exists but if no record exist it errors because I am trying to examine the ProjectName property of a null object. I realise I could cast the object to a variable and test if its null before storing the ProjectName into the ViewData but am just wondering if there is a neater way of doing this?
I know its a simple question and I could just work around it but if there is a better way of doing this it would be good to know.
Thanks
Gavin
var project = db.Projects.FirstOrDefault(p => p.ProjectId == task.ProjectId);
if (project != null)
{
ViewData["ProjectName"] = project.ProjectName;
}
else
{
//........
}
No cast needed.
Or skip the condition altogether and do this:
ViewData["ProjectName"] = db.Projects.Where(p => p.ProjectId == task.ProjectId)
.Select(p => p.ProjectName).FirstOrDefault();

StackOverflowException caused by a linq query

edit #2: Question solved halfways. Look below
As a follow-up question, does anyone know of a non-intrusive way to solve what i'm trying to do below (namely, linking objects to each other without triggering infinite loops)?
I try to create a asp.net-mvc web application, and get a StackOverFlowException. A controller triggers the following command:
public ActionResult ShowCountry(int id)
{
Country country = _gameService.GetCountry(id);
return View(country);
}
The GameService handles it like this (WithCountryId is an extension):
public Country GetCountry(int id)
{
return _gameRepository.GetCountries().WithCountryId(id).SingleOrDefault();
}
The GameRepository handles it like this:
public IQueryable<Country> GetCountries()
{
var countries = from c in _db.Countries
select new Country
{
Id = c.Id,
Name = c.Name,
ShortDescription = c.ShortDescription,
FlagImage = c.FlagImage,
Game = GetGames().Where(g => g.Id == c.GameId).SingleOrDefault(),
SubRegion = GetSubRegions().Where(sr => sr.Id == c.SubRegionId).SingleOrDefault(),
};
return countries;
}
The GetGames() method causes the StackOverflowException:
public IQueryable<Game> GetGames()
{
var games = from g in _db.Games
select new Game
{
Id = g.Id,
Name = g.Name
};
return games;
}
My Business objects are different from the linq2sql classes, that's why I fill them with a select new.
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
edit #1: I have found the culprit, it's the following method, it triggers the GetCountries() method which in return triggers the GetSubRegions() again, ad nauseam:
public IQueryable<SubRegion> GetSubRegions()
{
return from sr in _db.SubRegions
select new SubRegion
{
Id = sr.Id,
Name = sr.Name,
ShortDescription = sr.ShortDescription,
Game = GetGames().Where(g => g.Id == sr.GameId).SingleOrDefault(),
Region = GetRegions().Where(r => r.Id == sr.RegionId).SingleOrDefault(),
Countries = new LazyList<Country>(GetCountries().Where(c => c.SubRegion.Id == sr.Id))
};
}
Might have to think of something else here :) That's what happens when you think in an OO mindset because of too much coffee
Hai! I think your models are recursively calling a method unintentionally, which results in the stack overflow. Like, for instance, your Subregion object is trying to get Country objects, which in turn have to get Subregions.
Anyhow, it always helps to check the stack in a StackOverflow exception. If you see a property being accessed over and over, its most likely because you're doing something like this:
public object MyProperty { set { MyProperty = value; }}
Its easier to spot situations like yours, where method A calls method B which calls method A, because you can see the same methods showing up two or more times in the call stack.
The problem might be this: countries have subregions and subregions have countries. I don't know how you implement the lazy list, but that might keep calling GetCountries and then GetSubRegions and so on. To find that out, I would launch the debugger en set breakpoints on the GetCountries and GetSubRegions method headers.
I tried similar patterns with LinqToSql, but it's hard to make bidirectional navigation work without affecting the performance to much. That's one of the reasons I'm using NHibernate right now.
To answer your edited question, namely: "linking objects to each other without triggering infinite loops":
Assuming you've got some sort of relation where both sides need to know about the other... get hold of all the relevant entities in both sides, then link them together, rather than trying to make the fetch of one side automatically fetch the other. Or just make one side fetch the other, and then fix up the remaining one. So in your case, the options would be:
Option 1:
Fetch all countries (leaving Subregions blank)
Fetch all Subregions (leaving Countries blank)
For each Subregion, look through the list of Countries and add the Subregion to the Country and the Country to the Subregion
Option 2:
Fetch all countries (leaving Subregions blank)
Fetch all Subregions, setting Subregion.Countries via the countries list fetched above
For each subregion, go through all its countries and add it to that country
(Or reverse country and subregion)
They're basically equialent answers, it just changes when you do some of the linking.

Resources