[updated]
What i want is have 2 column and the first column display the unique name of the project and the second column display the tasks belong to associated project, any help guys please!!
#foreach (var project in project.GroupBy(project => project.Project)
{
<tr>
<td>
#project.Key
</td>
</tr>
}
}
</table>
Since you're already in a codeblock with the first #foreach, you can remove the # sign for the 2nd one..
#foreach (var project in person.GroupBy(project => project.Project, entry => entry))
{
foreach (var task in person.GroupBy(task => task.Task, entry => entry))
{
Remove the # sign on the second for each. is not needed since you're already in a Razor block
Related
I'm new with Entity Framework and razor pages, I´m very familiar with asp classic, but know I'm trying to learn something more actual.
How can I retrieve values from a join query in a model to the page/view.
In model I have:
IQueryable<TabQuotas> quotasIQ = from s in _context.TabQuotas
join s2 in _context.ApplicationUser
on s.Socio equals s2.Socio
select s;
And in page/view:
#foreach (var item in Model.TabQuotas) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Socio)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nome)
</td>
<tr>
}
"item.socio" which is from the first table in join, works perfect, but "item.Nome" which is from the second table, I can't find out how to retrieve the value from the query. It keep telling me that "TabQuotas" does not contain a definition for "Nome"...
Could someone help me with it?
I figure it out by my self.
For those how could have the same question, here is the answer.
First of all we have to create a model with all the values we want to retrieve from the data base.
Then on the .cs file:
var quotasIQ = from s in _context.TabQuotas
join s2 in _context.ApplicationUser
on s.Socio equals s2.Socio
select new ListQuotas
{
Id = q.Id,
Email = n.Email
};
Where ListQuotas is model class we created before.
And that's it.
I hope I can be useful to someone.
I have created two ViewBags which contain different values.
ViewBag.attendingEvents = attendingIds;
ViewBag.notAttendingEvent = notAttendingIds;
The attendingIds contain the ids of all the users which are attending the event whereas notAttendingIds contain the ids of all the users which are not attending the event.
It's showing me too many button since I am looping through. If there are 100 users attending the event then its showing me 100 Remove buttons with one record because the loop. What's the best approach to solve this problem?
#foreach (var user in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => user.Name)
</td>
<td>
#foreach(var record in ViewBag.attendingEvents as IList<User>) { Remove }
</td>
</tr>
}
Your Problem:
It's showing me too many button since I am looping through. If there are 100 users attending the event then its showing me 100 Remove buttons with one record because the loop. What's the best approach to solve this problem?
Best approach or solution:
You are getting the above problem, because there is a foreach to put the button, actually its not neccessary, you simply change your code like below
#foreach (var user in Model.User)
{
<tr>
<td>
#Html.DisplayFor(modelItem => user.Name)
</td>
<td>
string[] Users_attendingEvents = string[](ViewBag.attendingEvents);
#if(Users_attendingEvents.Contains(user.Id))
{
Remove
}
</td>
</tr>
}
you may also take at look at this link for additional info :how to use .contains in Viewbag in asp.net mvc
Hope it helps
Thanks
This is my solution if I have understood your question correct and if you want only those users who attend the meeting to be able to have the remove button. You need to loop through the result of users and check if they exist in your attendable id list.
#foreach (var user in Model.User)
{
<tr>
<td>
#Html.DisplayFor(modelItem => user.Name)
</td>
<td>
#if(ViewBag.attendingEvents.Contains(user.Id))
{ Remove }
</td>
</tr>
}
I have a problem with calls to action with POST attribute exclusively from Grid.MVC tool.
I set up a column within the Grid.MVC tool, setting the property RenderValueAs follows:
#Html.Grid(Model).Columns(columns =>
{
// other lines...
columns.Add().Encoded(false)
.Sanitized(false)
.RenderValueAs(item => Html.ActionLink("Delete", "Delete", new { item.ID }));
}).WithPaging(3).Sortable(true)
In my controller I have set the following code which refers to the Delete action:
[HttpPost]
public ActionResult Delete(int id)
{
// anything here
return RedirectToAction("Index");
}
The best practices tell you that the action method should support only POST requests, because deleting objects is not an idempotent operation. This because browsers and caches are free to make GET requests without the user’s explicit consent, and so I must be careful to avoid making changes as a consequence of GET requests.
But, when I try to apply this configuration I have the next error:
Server Error in application '/'
Can not find the resource.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly
But if I remove the [HttpPost] attribute the code works. Is this behavior correct?
Thanks
UPDATE:
Bayu, you have reason, now I explain the problem from another scenario: I had my View as follows:
<table>
<tr>
<th>ID</th>
#*another columns*#
<th>Name</th>
<th>Actions</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#item.ID</td>
#*another columns*#
<td>#item.Name</td>
<td>
#using (Html.BeginForm("Delete", "Admin"))
{
#Html.Hidden("ID", item.ID)
<input type="submit"
value="Delete row" />
}
</td>
</tr>
}
</table>
That is, I used HTML tables, and therefore I could use an input to build a button that allows me to delete a row from the table.
Now, I want to use the tool Grid.View (because among other benefits allows me effortlessly filter columns), but I can not use an input for this purpose.
You have any idea how?
Change new { item.ID }) to new {id = item.ID })
Currently in MVC, we have to define columns manually whenever we want to list out items:
<tr>
<td>
#Model.Name
</td>
<td>
#Model.Age
</td>
<td>
#Model.Gender
</td>
</tr>
What I want to do however, is to have a ViewModel where we specify which columns should be used, something like:
var model = new PersonViewModel(
// List of persons
CollectionOfPersons,
// List of columns that we want to display
new Expression<Func<Person, object>>[]
{
x => x.Name,
x => x.Age,
x => x.Gender
});
Then in our view, all I need to do is:
<tr>
// Model.Predicates is our ViewModel's selected columns
#foreach(var predicate in Model.Predicates)
{
<td>
// This would basically loop each pre-defined lambda expression in our ViewModel
#Html.DisplayFor(predicate)
</td>
}
</tr>
I have to admit I have a very weak understanding of expressions, and I have so far been unsuccessful in looking for information. Does anyone have any idea if this is possible to do?
Seems like the html helpers don't work like that (passing in the expression as a variable). The compiler explicitly needs an expression to be able to determine the TModel and TResult types to be able to work.
I'll use the famous NerdDinner as an example here.
I have a search page where the user can enter a search string and then see the result in a table below. The user can also add more results to the table, like this:
Search for dinners today and display in a table.
Search for dinners tomorrow and add the result to the table.
The table will now show dinners today and tomorrow.
The user is also able to remove dinners from the table by clicking on them, one by one.
I need to generate a pdf with the results in the table. Not like a print screen because the pdf has it's own layout. I just need the data in the table. Preferably in a list of Dinner models.
Right now I can generate a pdf from a list of Dinner models. But once I've printed them to the table and the user has manipulated it I don't know how to get it back to a list of Dinner models.
Another solution could be to keep the Id's hidden in the table and then do another search in the DB with the Id's from the table (after the user has manipulated it). At least then I would get the result in the form of a list of Dinners. But this seems redundant to me.
Has anyone had a similar problem and how did you solve it?
You could put the table inside an html <form> and on each row in addition to the label you could have a hidden field:
#model IEnumerable<Dinner>
#using (Html.BeginForm())
{
<table>
<thead>
<tr>
<th>Prop1</th>
<th>Prop2</th>
<th>Prop3</th>
</tr>
</thead>
<tbody>
#Html.EditorForModel()
</tbody>
</table>
<input type="submit" value="Export to PDF" />
}
and in the editor template:
#model Dinner
<tr>
<td>
#Html.DisplayFor(x => x.Prop1)
#Html.HiddenFor(x => x.Prop1)
</td>
<td>
#Html.DisplayFor(x => x.Prop2)
#Html.HiddenFor(x => x.Prop2)
</td>
<td>
#Html.DisplayFor(x => x.Prop3)
#Html.HiddenFor(x => x.Prop3)
</td>
</tr>
Now this form could be submitted to the following controller action:
public ActionResult GeneratePdf(IEnumerable<Dinner> dinners)
{
byte[] pdf = ...
return File(pdf, "application/pdf", "dinners.pdf");
}
You may also checkout the following blog post for managing a variable length list in order to keep input field names in sync for the binder when adding/removing elements.