How to use foreach inside webgrid + MVC 3 - asp.net-mvc-3

I have webgrid as below in MVC:how to show list of values in a single row in column in webgrid.I am using foreach inside webgrid column but it is unrecognized
Col1 Col2 Col3
---------------
1 | zzz | t
| xxx |
| yyy |
---------------
2 | aaa | P
| bbb |
| ccc |
Above grid is just sample Example..i want to show data.
In 2nd column i want to show list of values in single row.Below code I tried,But i get Error foreach is invalid in webgrid.
In Model:
public class Employee
{
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string RowId { get; set; }
public string Error { get; set; }
public List<string> tbldata { get; set; }
public List<Employee> lstEmp { get; set; }
}
In Controller:
public ActionResult Index()
{
Employee emp = new Employee();
List<string> tbldata3 = new List<string>();
tbldata3.Add("xxx");
tbldata3.Add("yyy");
tbldata3.Add("zzz");
List<string> tbldata1 = new List<string>();
tbldata1.Add("gggh");
tbldata1.Add("hhhh");
tbldata1.Add("ffff");
List<string> tbldata2 = new List<string>();
tbldata2.Add("ppp");
tbldata2.Add("oooo");
tbldata2.Add("iii");
List<Employee> lstempo = new List<Employee>();
lstempo.Add(new Employee { EmployeeId = "100", EmployeeName = "aaa", RowId = "111", Error = "3434", tbldata = tbldata1 });
lstempo.Add(new Employee { EmployeeId = "101", EmployeeName = "BB", RowId = "222", Error = "6767", tbldata = tbldata2 });
lstempo.Add(new Employee { EmployeeId = "102", EmployeeName = "ccc", RowId = "333", Error = "898", tbldata = tbldata3 });
emp.lstEmp = lstempo;
return View(emp);
}
In View:
#{
var grid = new WebGrid(source: Model.lstEmp,
canSort: true,
rowsPerPage: 10,
ajaxUpdateContainerId: "grdCurrentReqDetails"
);
}
#grid.GetHtml(
tableStyle: "webGrid",
headerStyle: "gridHead",
alternatingRowStyle: "alt",
columns: grid.Columns
(
grid.Column("EmployeeId", header: "EmployeeId"),
grid.Column("EmployeeName", header: "EmployeeName"),
grid.Column("RowId", header: "RowId"),
grid.Column("Error", header: "Error"),
grid.Column("Checks", format: (item) => { return new HtmlString(
"<table><tr><td>"+
foreach(var t in item.tbldata)
{
t.ToString();
}
+"</td></tr></table>"
); })
)
)

Related

Setting the default value of multiple dropdown lists on page load

I have a model,
public class Customer
{
public string Name { get; set;}
public string CountryCode { get; set;}
}
In the controller
var model = new List<Customer>
{
new Customer { Name = "foo", CountryCode = "US"},
new Customer { Name = "bar", CountryCode = "UK",
};
return PartialView("_Edit", model);
An extension method for displaying all countries:-
public class CountryList
{
public static IEnumerable<SelectListItem> CountrySelectList
{
get
{
var list = new List<SelectListItem>()
{
new SelectListItem { Value = "US", Text="US" },
new SelectListItem { Value = "UK", Text="UK" },
};
return list;
}
}
}
In the PartialView
#model List<Customer>
#Html.DropDownListFor(model => model[i].CountryCode, CountryList.CountrySelectList, "Select Country Type")
But the drop down doesn't select each customer's country code? Any thoughts?
PS: It is using model[i] => which is of type Customer, for simplicity i had removed the forloop before rendering the html tags.
#using(Html.BeginForm())
{
for(int i = 0; i < Model.Count(); i++)
{
#Html.TextBoxFor(model => model[i].Name)
#Html.DropDownListFor..........
}
}
Because your CoutryList helper does returns a list of SelectListItems that all have Selected property set to False (which is default).
I would rewrite your helper method as follows:
public static IEnumerable<SelectListItem> CountrySelectList(string selectedCountryCode)
{
get
{
var list = new List<SelectListItem>()
{
new SelectListItem { Value = "US", Text="US" },
new SelectListItem { Value = "UK", Text="UK" },
};
var selectedListItem = list.FirstOrDefault(t=>t.Value== selectedCountryCode);
if(selectedListItem!=null)
selectedListItem.Selected=true;
return list;
}
}
In view:
#Html.DropDownListFor(model => model[i].Customer, CountryList.CountrySelectList(model[i].Customer.CountryCode), "Select Country Type")

How to load and search data using edmx

I am trying to load the data into a dropdownlist in a nested master page but the Model in View is always null. How can I do this?
In model
public class AllInOneModel
{
public string City { get; set; }
public IEnumerable<City> cities { get; set; }
}
In controller
public ActionResult Add()
{
return View(new AllInOneModel());
}
In View
#model IBilik.Models.AllInOneModel
#Html.DropDownListFor(model => model.City,(SelectList)Model.cities)
Personally I would skip the "AllInOneModel" and stick to sending the single city to the view.
The controller action could look somewhat like this.
public ActionResult Index()
{
//TODO: get current cities from database
List<City> cities = new List<City>
{
new City { CityID = 1, CityName = "City1" },
new City { CityID = 2, CityName = "City2" },
new City { CityID = 3, CityName = "City3" }
};
// Create the list of selectlistitems to populate the dropdown
List<SelectListItem> listItems = new List<SelectListItem>();
foreach(var c in cities)
{
listItems.Add(new SelectListItem { Value = c.CityID.ToString(), Text = c.CityName });
}
//Throw them into viewbag
ViewBag.ListItems = listItems;
//TODO get some city (perhaps from db) to send to view
var city = new City { CityID = 1, CityName = "City1" };
return View(city);
}
And then you would render the view in this way.
#model IBilik.Models.City
#Html.DropDownListFor(model => model.CityID, ViewBag.ListItems as List<SelectListItem>)

How can I select data from multiple tables?

In my MVC project, I have some tables like this:
Form (FormID, SectionID)
Section (SectionID, SectionName)
SectionQuestion (SectionID, QuestionID)
Question (QuestionID, Content)
A form has multiple sections, and a section has some questions.
I can get all question for the FormID. But I want to get a list of sections (which contain questions) for the model.
It means in the view I want to do something like this:
#Model IEnumerable<MedialForm.Models.Sections>
foreach (var section in Model)
{
//Show questions
}
Can you guys help me? :)
You will not see a list of sections for a form, since the Form can only have 1 section. (i.e. the SectionID is defined in Form, and not FormID in Section). However the following Linq query will return the section and the associated questions for a specified FormID:
void Main()
{
var sections =
new []
{
new Section { SectionID = 1, SectionName = "SectionName1" },
new Section { SectionID = 2, SectionName = "SectionName2" }
};
var forms =
new []
{
new Form { FormID = 1, SectionID = 1 },
new Form { FormID = 2, SectionID = 1 },
new Form { FormID = 3, SectionID = 2 },
new Form { FormID = 4, SectionID = 2 }
};
var questions =
new[]
{
new Question { QuestionID = 1, Content = "Question1" },
new Question { QuestionID = 2, Content = "Question2" }
};
var sectionQuestions =
new[]
{
new SectionQuestion { SectionID = 1, QuestionID = 1 },
new SectionQuestion { SectionID = 2, QuestionID = 1 },
new SectionQuestion { SectionID = 2, QuestionID = 2 }
};
var formId = 4;
var result = forms
.Join(
sections,
f => f.SectionID,
s => s.SectionID,
(f, s) => new { Form = f, Section = s })
.Join(
sectionQuestions,
jfs => jfs.Section.SectionID,
sq => sq.SectionID,
(jfs, sq) => new { Form = jfs.Form, Section = jfs.Section, sq.QuestionID })
.Join(
questions,
jfsq => jfsq.QuestionID,
q => q.QuestionID,
(jfsq, q) => new { Form = jfsq.Form, Section = jfsq.Section, Question = q })
.Where(f => f.Form.FormID == formId)
.GroupBy(f => f.Section.SectionID)
.Select(grp => new { SectionID = grp.Key, Questions = grp.Select(g => g.Question)});
Console.WriteLine($"For Form: {formId} the following sections with their questions were found: {String.Join(", ", result.Select(r => $"SectionID: {r.SectionID}, QuestionIDs: [{String.Join(", ", r.Questions.Select(q => q.QuestionID))}]"))}");
}
public class Form
{
public Int32 FormID { get; set; }
public Int32 SectionID { get; set; }
}
public class Section
{
public Int32 SectionID { get; set; }
public String SectionName { get; set; }
}
public class SectionQuestion
{
public Int32 SectionID { get; set; }
public Int32 QuestionID { get; set; }
}
public class Question
{
public Int32 QuestionID { get; set; }
public String Content { get; set; }
}
This will return the following result:
For Form: 4 the following sections with their questions were found: SectionID: 2, QuestionIDs: [1, 2]

one to many relationship in entity framewrok 4.1 code first

I am initializing the entities like this:
TasksListDB db = new TasksListDB();
public ActionResult Index()
{
var tasks1 = new List<Task>()
{
new Task { Id=1, Name = "Task 1", Difficulty = 1, DateCreated = DateTime.Parse("1/12/2011") , IsDone= true },
new Task { Id=2, Name = "Task 2", Difficulty = 2, DateCreated = DateTime.Parse("11/2/2011") , IsDone = false}
};
var tasks2 = new List<Task>()
{
new Task { Id=3, Name = "Task 3", Difficulty = 3, DateCreated = DateTime.Parse("11/2/2011") , IsDone = false},
new Task { Id=4, Name = "Task 4", Difficulty = 5, DateCreated = DateTime.Parse("1/2/2010") , IsDone= true }
};
tasks1.ForEach(t => db.Tasks.Add(t));
tasks2.ForEach(t => db.Tasks.Add(t));
var Persons = new List<Person> {
new Person { Id= 1 , Age= 10, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed" },
new Person { Id= 2 , Age= 10, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed" },
new Person { Id= 3 , Age= 10, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed" },
new Person { Id= 4 , Age= 10, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed" }};
Persons.ForEach(p => db.Persons.Add(p));
return View(db.Tasks);
}
my db context looks like this:
public class TasksListDB : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Task> Tasks { get; set; }
}
I want to assign tasks to persons how can I do this ?
My model looks like this :
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string EmailAddress { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
}
public class Task
{
public int Id { get; set; }
public string Name { get; set; }
[Required]
public DateTime DateCreated { get; set; }
[Required]
[Range(1,5,ErrorMessage="Difficulty must be between 1 and 5")]
public int Difficulty { get; set; }
public bool IsDone { get; set; }
public virtual Person Person { get; set; }
}
When I run my mvc application, Person and Task tables are created but juntion table PersonTask not created.
[EDIT]
I am assigning tasks like this in initializer class:
var t1 = new Task { Id = 1, Name = "Urgent Task", DateCreated = DateTime.Now, Difficulty = 2, IsDone = true };
var t2 = new Task { Id = 2, Name = "Business Task", DateCreated = DateTime.Now, Difficulty = 1, IsDone = true };
var t3 = new Task { Id = 3, Name = "Home Task", DateCreated = DateTime.Now, Difficulty = 2, IsDone = false };
context.Tasks.Add(t1);
context.Tasks.Add(t2);
context.Tasks.Add(t3);
var Persons = new List<Person> {
new Person { Id= 1 , Age= 40, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed", Tasks= new List<Task> { t1,t2 }},
new Person { Id= 2 , Age= 30, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed" , Tasks= new List<Task> { t1} },
new Person { Id= 3 , Age= 29, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed" , Tasks= new List<Task> { t3,t2 } },
new Person { Id= 4 , Age= 35, EmailAddress= "asif_hameed_37#hotmail.com", FirstName= "Asif", LastName="Hameed" , Tasks= new List<Task> { t1,t3 } }};
context.Persons.Add(Persons[0]);
context.Persons.Add(Persons[1]);
context.Persons.Add(Persons[2]);
context.Persons.Add(Persons[3]);
context.SaveChanges();
but when i see the task table in sql server, it looks like this:
Id Name DateCreated Difficulty IsDone Person_Id
1 Urgent Task 2011-04-24 19:32:03.990 2 1 4
2 Business Task 2011-04-24 19:32:03.990 1 1 3
3 Home Task 2011-04-24 19:32:03.990 2 0 4
I assume that person table should have tasks not the task table should have person Id
Please suggest solution.
Junction table will not be created because you have defined one-to-many relation not many-to-many. The Task entity in your model can be assigned only to single Person not to many persons.
If you want to assing Task to Person simply run:
person.Tasks.Add(task);

Using the ALL operator in linq to filter child items of EntitySet

I have a two objects as follows:
public class Item
{
public int ItemId {get;set;}
public string ItemName {get;set;}
public List<Tag> ItemTags {get;set;}
public DateTime DateCreated {get;set;}
}
public class Tag
{
public int TagId {get;set;}
public string TagName {get;set;}
}
These are LINQ-to-SQL objects, so the ItemTags will be an EntitySet.
I am trying to perform a search query where a user can provide a comma delimited list of tags as a search filter.
How do I filter my list of items to those which contains all of the tags in the comma delimited list.
EDIT2
e.g.
Item1 has tags of Apple, Banana, Orange
Item2 has tags of Banana, Orange
Item3 has tags of Pineapple, Orange
If the tag filter is "Banana, Orange" I need the results to be Item1 and Item2.
/EDIT2
This is what I have tried thus far:
string tags = "Manchester United,European Cup,2008";
List<string> tagsList = tags.Trim().ToLower()
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Distinct(StringComparer.CurrentCultureIgnoreCase)
.ToList();
List<Item> itemList = ItemRepository.FetchAll();
var query = itemList
.OrderByDescending(p => p.DateCreated)
.ToList();
if (tagsList.Count() > 0)
{
query = query
.Where(p => p.ItemTags
.Select(q => q.TagName.ToLower())
.All(r => tagsList.Contains(r)))
.ToList();
}
However, this doesn't seem to work. Any ideas on what I am doing wrong please?
EDIT1: tags are trimmed and are 'lowercased'.
That because you're puting the tags from the items to lowercase, but not the searched tags.
With this modification it should work:
List<string> tagsList = tags
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.ToLower())
.Distinct()
.ToList();
EDIT: OK, I see what the problem is: you're doing it backwards. You're searching for items that have only the tags that you're looking for.
Try that instead:
query =
(from item in query
let itemTags = p.ItemTags.Select(it => it.TagName.ToLower())
where tags.All(t => itemTags.Contains(t))
select item).ToList();
UPDATE: here's a version with the lambda syntax. It's pretty ugly because of the temporary anonymous type, but that's how the let clause translates to lambda...
query =
query.Select(item => new { item, itemTags = item.ItemTags.Select(it => it.TagName.ToLower()) })
.Where(x => tagsList.All(t => x.itemTags.Contains(t)))
.Select(x => x.item)
.ToList();
I think you need to do something like this:
var query = itemList.OrderByDescending(p => p.DateCreated).ToList();
var results = query.Where(i => i.ItemTags
.All(it => tagsList.Contains(it.TagName.ToLower())));
Then results should then be a list of matching items.
PS. Your code shows you fetching itemList as a List from your repository and then sorting by date created. This means the sorting isn't being done in the database. Once you turn something into a List you give up the benefits of deferred execution as you will bring back the entire collection into memory.
EDIT: Here's the test code to prove it works in Linq to Objects:
public class Item
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public List<Tag> ItemTags { get; set; }
public DateTime DateCreated { get; set; }
}
public class Tag
{
public int TagId { get; set; }
public string TagName { get; set; }
}
class Program
{
static void Main(string[] args)
{
RunTags();
}
private static void RunTags()
{
Item i1 = new Item()
{
ItemId = 1,
ItemName = "Item1",
ItemTags = new List<Tag>() { new Tag { TagId = 1, TagName = "2008" }, new Tag { TagId = 2, TagName = "Donkey" } }
};
Item i2 = new Item()
{
ItemId = 2,
ItemName = "Item2",
ItemTags = new List<Tag>() { new Tag { TagId = 4, TagName = "Cat" }, new Tag { TagId = 2, TagName = "Donkey" }, new Tag { TagId = 3, TagName = "Seattle" } }
};
Item i3 = new Item()
{
ItemId = 3,
ItemName = "Item3",
ItemTags = new List<Tag>() { new Tag { TagId = 523, TagName = "Manchester united" }, new Tag { TagId = 10, TagName = "European Cup" }, new Tag { TagId = 1, TagName = "2008" } }
};
Item i4 = new Item()
{
ItemId = 4,
ItemName = "Item4",
ItemTags = new List<Tag>() { new Tag { TagId = 05, TagName = "Banana" }, new Tag { TagId = 140, TagName = "Foo" }, new Tag { TagId = 4, TagName = "Cat" } }
};
Item i5 = new Item()
{
ItemId = 5,
ItemName = "Item5",
ItemTags = new List<Tag>() { new Tag { TagId = 05, TagName = "Banana" }, new Tag { TagId = 140, TagName = "Foo" } }
};
List<Item> itemList = new List<Item>() { i1, i2, i3, i4, i5 };
string tags = "Manchester United,European Cup,2008";
List<string> tagsList = tags.Trim().ToLower()
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Distinct(StringComparer.CurrentCultureIgnoreCase)
.ToList();
var query = itemList
.OrderByDescending(p => p.DateCreated).ToList();
var results = query.Where(i => i.ItemTags.All(it => tagsList.Contains(it.TagName.ToLower())));
foreach (var item in results)
{
Console.WriteLine(item.ItemName); // Should return "Item3"
}
Console.ReadLine();
}
If you want to match any of the tags in the Item's ItemTag list then just change All to Any i.e.
var results = query.Where(i => i.ItemTags.Any(it => tagsList.Contains(it.TagName.ToLower())));

Resources