Can I use IEnumerable<> inside a View? - c#

In _Layout.cshtml
#model DynaPortalMVC.Models.Page
#using System.Linq
<ul>
#IEnumerable<model.Page> pages = model.Where(x=>x.CompanyID == 1);
#foreach (var item in pages)
{
<li>item.Title</li>
}
</ul>
In view iam trying to filter the model object called 'page' and get a list of pages whose id is 1. I need to iterate through this to show the menu.
Code inside Controller
public ActionResult Menu(string PageName)
{
//
return View(PageName, db.Pages);
}
Please tell me, how to filter out this model object to a list? I get errors on using IEnumerable.
Solved
I changed the model object to IEnumerable in view page.
#model IEnumerable<DynaPortalMVC.Models.Page>

You can skip assigning the result of your query into an IEnumerable variable unless you will use it somewhere else on the page. So you can just do this:
#model DynaPortalMVC.Models.Page
#using System.Linq
<ul>
#foreach (var item in model.Where(x=>x.CompanyID == 1))
{
<li>#item.Title</li>
}
</ul>

You need
# {IEnumerable<model.Page> pages = Model.Where(x=>x.CompanyID == 1);}

#model IEnumerable<DynaPortalMVC.Models.Page>
#{
ViewBag.Title = "Page";
}

Related

URL as a concatenated string in ASP.NET MVC View

I am trying to create a custom url which is within a loop so that through each loop the produced url is different. The code looks like this:
#foreach (var car in Model)
{
<div class="container">
#{string country = Html.DisplayFor(modelCar => car.Country).ToString()}
#{string mapUrl = "https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=150x120&key=[insertkey]&center="
+ country}
<img src=#mapUrl />
</div>
}
The problem is the line where I define mapUrlrenders an error. What is the problem with this code?
Thanks in advance.
I think you are simply missing the semi columns for the variables and quotes for the image src tag.
Also i am not sure why you are calling DisplayFor to get the country variable name! DisplayFor returns an MvcHtml string and is usually used to get the encoded html markup to render to browser. Unless you have some crazy overloading of that (why would you do that on DisplayFor ? Use a simply helper method), do not misuse the DisplayFor helper
This should work.
#foreach (var car in Model)
{
<div class="container">
#{ var country = car.Country; } // i assume you just need the Country
#{ var mapUrl = "https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=150x120&key=[insertkey]&center=" + country; }
<img src="#mapUrl" />
</div>
}

ASP.NET mvc display int number in LabelFor

Why it's displaying data, but not the value 100
public ActionResult Index()
{
ViewBag.id = 100;
return View();
}
Index.cshtml
#model TestForm.Models.Data
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using(#Html.BeginForm())
{
#Html.LabelFor(model=>model.data,((int)#ViewBag.id))
}
Remove the '#' if you want to display 100 that you stuffed into a ViewBag
Viewbag:
ViewBag.id = "100";
Html:
#model TestForm.Models.Data
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using(#Html.BeginForm())
{
#Html.LabelFor(model=>model.data,((string /*LabelFor produces string lableText */)ViewBag.id))
}
Or:
#Html.Label("id", (int)ViewBag.id)
Instead of the LabelFor, you could always do the following:
<label>#Html.Raw(ViewBag.Id)</label>
LabelFor is really reserved for Model properties since the model is able to pass Data Types and Data Annotations like Email, Password.
By doing it the more raw HTML way, you can style is appropriately like you would any other HTML element.
If you want to show 100 on label text, then why are you using Html.LabelFor? The first parameter of LabelFor shows the text of the property (or the DisplayAttribute inside your model), which in your case is data.
Use Html.Label instead, like this
#Html.Label("id", (int)ViewBag.id)
Or, in a simply way, use the html version:
<label>ViewBag.id</label>

passing collection to view

I have multiple methods that return either a simple type (string, ..) & methods that return collections Collection<Tuple<Model_name, string>>
I tried with a simple Collection<string> at first but when i used a Tempdata to pass the collection to the view it doesn't work.
Example :
Controller:
public ActionResult Index()
{
Collection<string> test_Q_Q = new Collection<string>();
test_Q_Q.add("abcd");
test_Q_Q.add("adbc");
Tempdata["test"] = test_Q_Q;
return view();
}
View:
<!--Bla Bla here-->
#foreach (var lst in Tempdata["test"]) //error here
{
<li> </li>
}
The real issue is that TempData is a stupid dictionary, and doesn't know that there's an IEnumerable stored in it's data. If you really wanted to stick with this approach, simply cast the TempData to the appropriate type, like so:
#foreach (var lst in (Collection<string>) TempData["test"])
{
<li> #lst </li>
}
Having said that, I don't think you should be using TempData. What I recommend is using a strongly typed Model object that gets passed into the view, something like this in the controller:
var model = new MyCustomType();
model.ListOfStrings = new Collection<string>();
model.ListOfStrings.Add("foo");
model.ListOfStrings.Add("blah"); // You get the idea
return View(model);
Then, in your view declare the type like so at the top:
#model MyCustomType
And address it like this:
#foreach (var item in Model.ListOfStrings)
{
<li> #item </li>
}
At the very least, I hope you would use ViewBag instead of TempData. As some of the comments have mentioned, TempData has a particular use, having to do with the lifetime of the HTTP request, and is not meant to be used the way you're using it. Good Luck!
Try closing your foreach loop test.
<!--Bla Bla here-->
#foreach (var lst in Tempdata["test"] ) // Close
{
<li> ???? </li>
}

Display only x numbers of items in index.cshtml

I'm making a newsfeed project in Visual Studios, MVC 3, Razor engine and I'm trying only to display, let's say 10, number of feeds at once.
Currently while I was getting the database going I used this index.cshtml:
#model IEnumerable<NyjiGrunnur.Models.Article>
#{
ViewBag.Title = "NewsFeed";
}
<h2>#ViewBag.Message</h2>
#foreach (var item in Model)
{
<div id="eitt">
<fieldset>
<legend>#Html.ActionLink( item.Name, "Edit", new { id=item.Id } )</legend>
<div>#item.Subject, #item.Created</div>
<p>#Html.Raw(item.Content.Replace(Environment.NewLine, "<br/>"))</p>
</fieldset>
</div>
}
The foreach takes every single item and I was wondering if I could use a for loop or something similar to display only the 10 newest feeds.
Thanks in advance.
You can keep a counter variable and check it before displaying the data
#{
int counter=0;
}
foreach (var item in Model)
{
counter++;
if(counter<=10)
{
<div id="eitt">#item.Name</div>
}
}
But it is better to do this at your Action method and return only 10 items to the view so that you don't need to contaminate your view by adding the if statement. You can use the Take method from LINQ to get the 10 items.
public ActionResult Newsfeed()
{
List<Article> articleList=new List<Article>();
articleLsit=GetListOfItemsFromSomewhere();
//now get only 10. you may apply sorting if needed
articleList=articleList.Take(10);
return View(articleList);
}
it will be better
#foreach (var item in Model.Take(10))
{
<div id="eitt">
<fieldset>
<legend>#Html.ActionLink( item.Name, "Edit", new { id=item.Id } )</legend>
<div>#item.Subject, #item.Created</div>
<p>#Html.Raw(item.Content.Replace(Environment.NewLine, "<br/>"))</p>
</fieldset>
</div>
}

Model Binding with variable number of items in List<T>

I have a model that can have a variable amount of items in a List<T>
In my view I then have the following:
#using (Html.BeginForm())
{
int count = Model.Data.Filters.Count;
for(int i = 0; i < count; i++)
{
<div>
#Html.TextBox("filtervalue" + i)
#Html.DropDownList("filteroptions"+i,Model.Data.Filters[i].FilterOptions)
</div>
}
#Html.Hidden("LinkID", Url.RequestContext.RouteData.Values["id"])
}
Is there a way in my controller so I can set up the POST action method to bind to a model with variable items in it?
Also how would I construct the model to cope with this?
Thanks
You coud use editor templates, it will be much easier:
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.Data.Filters)
#Html.Hidden("LinkID", Url.RequestContext.RouteData.Values["id"])
}
and inside the editor template (~/View/Shared/EditorTemplates/FilterModel.cshtml) which will be automatically rendered for each element of the Model.Data.Filters collection:
#model FilterModel
<div>
#Html.TextBoxFor(x => x.FilterValue)
#Html.DropDownListFor(x => x.SelectedFilterOption, Model.FilterOptions)
</div>
Now your POST controller action will simply look like this:
[HttpPost]
public ActionResult Foo(SomeViewModel model)
{
// model.Data.Filters will be properly bound here
...
}
Thanks to editor templates you no longer have to write any foreach loops in your views or worry about how to name your input fields, invent some indexed, ... so that the default model binder recognizes them on postback.

Categories

Resources