Using #helper ShowTree() - c#

#helper ShowTree(IEnumerable<CommentModel> comments) {
foreach (CommentModel c in comments)
{
// ...
I don't get how this works. Where does comments come from? Exactly what is this looping over?
I want to recursively display a List<CommentModel> from the model passed into the view. Each item in that list has its own list of CommentModels, and so on. Is this the right method to use to render those lists, and how do I use it?

in your view you can pass comment as parameter :
#model IEnumerable<CommentModel>
#ShowTree(Model)
#helper ShowTree(IEnumerable<CommentModel> comments)
{
//your code...
}
simply your action method can be something like this :
public ActionResult Comments()
{
var query = _commentsService.GetAll();
return View("comments",query);
}

Related

Handle data from ViewModel in View

I'm using a ViewModel to pass the data from two tables to the view. One table contains name of the staff and the second table contains data like number of hours they work per week. When I list the names from one table I also want to show the working hours that match that persons ID. Is it possible to use LINQ like where or equal to make this possible? Could someone show me a simple sample?
EDIT: Are there better ways to do this? Should I handle this in the Controller instead?
This is the code I'm using so far in the View:
#foreach (var item in Model.resourceList)
{
<p>#item.FirstName</p>
}
#foreach (var item in Model.activityList)
{
<p>#item.NumberOfHoursPerWeek</p>
}
If you're looping through this:
#foreach (var item in Model.resourceList)
{
...
}
Then within that loop you can match any element in Model.activityList just like any other LINQ query. Perhaps something like this?:
#Model.activityList.Single(a => a.SomeID == item.SomeID).NumberOfHoursPerWeek
The actual comparison (in this example, a.SomeID == item.SomeID) is up to you, as is the logic for the records you want to find (.Where(), .Single(), .First(), etc. depending on the behavior you expect) is up to you. But finding an element in a collection is the same in this view code as it would be in any server-side code.
Ignoring all design issues, here is a solution:
#foreach (var item in Model.resourceList)
{
#{
var numberOfHours = Model.activityList.First(_ => _.UserID == item.ID).NumberOfHoursPerWeek;
}
<p>#item.FirstName</p>
<p>#numberOfHours</p>
}
However, the View should usually be kept as simple as possible. The ViewModel is responsible for preparing the data for the View in an easily consumable form. If done right, you should not need any linq queries in your Views.
you can use it like this
with if
//just an example to make condition true not displaying the exact Property or condition
#if (true)
{
Model.Where(model=>model.UserID==User.UserID)
}
or with loop
#foreach (var item in Model.resourceList)
{
//just an example not displaying the exact Property
Model.Where(model=>model.UserID==User.UserID)
}

razor list<MyObject> element was not closed

I have a cshtml template and I'm using Razor to populate it. I'm passing an object that has several sub-lists inside it and I need to get the values from one of the items in one the sub-lists to use in the body of the text. So in the opening tag I have this:
#{
var myId = #Model.myId;
List<MyObject> newObj = #Model.MyList.Where(l => l.Id == myId).ToList();
}
But when I try to execute the template, it throws an error that '<'MyObject'>' was not closed, that all elements must have a matching self-closing tag or end tag. I understand that it seems to be reading this as an html tag, but why since its clearly inside the programming markup? Can I not call a list object in razor? If so, how do I get to this specific sub-list of items?
I've checked the rest of the page and the html has all its closing marks.
I think to fix your code you would have to do the following:
#{
var myId = Model.myId;
List<MyObject> newObj = Model.MyList.Where(l => l.Id == myId).ToList();
}
Which simply removes the # in front of the Model's.
However I feel that a better solution to your problem is to try and keep the logic code in your controller rather than your view.
As an example, if you are using a Partial View.
In your view you could call an action and pass in your model like this:
#Html.Action("MyAction", Model)
This would call a controller action that would do your select i.e.
[ChildActionOnly]
public ActionResult MyAction(MyModel model)
{
var newList = model.MyList.Where(l => l.Id == myId).ToList();
return PartialView("_MyPartial", newList);
}
Then use the #model attribute within your partial i.e.
#model List<MyObject>

Selected column in For Loop ASP.NET MVC3

I have a following function in a controller. It is called from index.cshtml. var relays works fine and I got the replays.count(). PRESETDETAILS has some columns from which I want to access specific columns in a loop (like I have mentioned in response.write).
Kindly tell me how I can get the specific columns in the for loop.
#region "Apply Preset Handlers"
public ActionResult btnApply_Click(int? id)
{
var relays = db.PRESETDETAILS.ToList().Where(t => (t.PRESETID).Equals(id));
for (int k = 0; k < relays.Count(); k++)
{
Response.Write(relays.Select(s => new relays{PRESETDETAILID = s.PRESETDETAILID }).ToString());
}
return View("Index");
}
#endregion
you need to loop through them, you're simply select the same things over and over...
var relays = db.PRESETDETAILS.Where(t => t.PRESETID == id).ToList();
foreach (var replay in replays)
{
Response.Write(string.Format("{0}", relay.ID));
}
NOW... looking at your code:
always use ToList() at the end of the query;
ToList() actually makes the call to the database, until then, it's just a promise
Don't use Response.Write in your Controller, send the data to the View instead
your code should be:
public ActionResult btnApply_Click(int? id)
{
var model = db.PRESETDETAILS.Where(t => t.PRESETID == id).ToList();
return View(model);
}
in your View you can loop through the records
#model List<YOUR_CLASS>
<ul>
#foreach(var replay in Model)
{
<li>#replay.ID</li>
}
</ul>
I can see that some MVC conventions are not yet in place with you, and I know it can be somewhat overwhelm from someone that comes from WebForms or a linear code approach, but why don't you take some time and check the FREE available course about ASP.MVC in the ASP.NET Website?
See the videos in the right side of this page: http://www.asp.net/mvc

Select List returns System.Data.Entity.DynamixProxies instead of values in MVC asp.net C#

I have got two different tables. User and ProjectDetails. There are two different controllers as well to do CRUD operations on these tables. Now, I have a case where, in the User CREATE operation, I have to select the Project from the List of Projects in ProjectDetails. I tried the following:
In the user model, I created this line:
public IEnumerable<ProjectDetail> ProjectDetail { get; set; }
And in the controller, in the create Action, I have added the following code:
public ActionResult Create()
{
var model = new UserDetail
{
ProjectDetail = db1.ProjectDetails
};
return View(model);
}
And in the create view, I am trying to get the list of Project IDs as follows:
#Html.DropDownListFor( x => x.ProjectDetail, new SelectList(Model.ProjectDetail, "Project ID"))
However, wen i run, i get the number of lines (as equal to the number of projects) as
System.Data.Entity.DynamicProxies.ProjectDetails_F########### (Some numbers)..
Please can someone help me?
Regards,
Hari
[EDIT] - I checked in the debug mode and found the following.. Tried attaching the image..
I drilled down that Proxy things and found ProjectID there. How can I get that?
You are using a wrong overload, use this instead:
#Html.DropDownListFor( x => x.ProjectDetail,
new SelectList(Model.ProjectDetail, "ProjectId","ProjectName"))
// where ProjectId is the unique identifier field of `ProjectDetail`
// and `ProjectName` is the text you want to show in the dropdown
In your code you are not telling the html helper what properties to use for the datavalue and the datatext. The overload you use is the one where you tell the htmlhelper which value is selected.
You can do something like
var projection = db1.ProjectDetails.Select(t => new ProjectDetailsViewModel
{
Prop1 = t.Prop1,
Prop2 = t.Prop2
});
Can you try
public ActionResult Create()
{
var model = new UserDetail
{
ProjectDetail = db1.ProjectDetails.ToList()
};
return View(model);
}

Passing Field Name to Razor #helper in Webmatrix pages C#

This code obtains a listing of unique org names for display within my .cshtml page:
IEnumerable<dynamic> data = db.Query("Select * from provider
where submitter_element = '210300'");
//the 210300 could be any value passed to the query
var items = data.Select(i => new { i.org_name }).Distinct();
foreach(var name in items){
<text>#name.org_name<br></text>
The records in data are each unique themselves, but the data in each field contains the same values i.e. multiple providers have the same org_name.
I want to be able to reuse the data multiple times to create multiple unique lists. I was hoping to pass this to a #helper for display. To that end, I have the following:
#helper ListBoxDistinctDisplay(IEnumerable<dynamic> queryResult)
{
IEnumerable<dynamic> distinctItems = queryResult.Select(i => new { i.org_name }).Distinct();
foreach(var listItem in distinctItems){
<text>#listItem.org_name<br></text>
}
Then in my .cshtml page I do this:
#DisplayHelpers.ListBoxDistinctDisplay(data)
...and BINGO, I get my unique list on my "view" page.
The works perfectly, except as you see I am having to indicate .org_name within the helper.
My question is how can I pass the field name (org_name) into the helper so that my helper can be re-used no matter he field name?
OR...is there a totally different approach all together that I am unaware of?
THANKS!
Since you like to use dynamic, I'll stick with that.
You may want to pass selector:
#helper ListBoxDistinctDisplay(IEnumerable<dynamic> queryResult, Func<dynamic, dynamic> selector)
{
IEnumerable<dynamic> distinctItems = queryResult.Select(x => new {selectedField = selector(x)}).Distinct();
foreach (var listItem in distinctItems)
{
<text>#listItem.selectedField<br/></text>
}
}
Call it:
#DisplayHelpers.ListBoxDistinctDisplay(data, x => x.org_name)

Categories