I am learning MVC4. I could display records in a tabular format using foreach.
Now, I need to display theDescription of (only) first Topic object in a label. I need to do it without a foreach. How can we do it?
VIEW
#model MvcSampleApplication.Models.LabelDisplay
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
foreach (var item in Model.Topics.Select((model, index) => new { index, model }))
{
<div>#(item.index) --- #item.model.Description---- #item.model.Code</div> <div></div>
}
}
Controller Action
public ActionResult Index()
{
LabelDisplay model = new LabelDisplay();
Topic t = new Topic();
t.Description = "Computer";
t.Code=101;
Topic t3 = new Topic();
t3.Description = "Electrical";
t3.Code = 102;
model.Topics = new List<Topic>();
model.Topics.Add(t);
model.Topics.Add(t3);
return View(model);
}
Model
namespace MvcSampleApplication.Models
{
public class LabelDisplay
{
public List<Topic> Topics;
}
public class Topic
{
public string Description { get; set; }
public int Code { get; set; }
}
}
REFERENCE
Iterate through collection and print Index and Item in Razor
I need to display theDescription of (only) first Topic object in a label
Unless I totally misunderstood you, selecting the first item (only) in your view would look something like:
#if (Model.Topics.Any())
{
#Html.DisplayFor(x => x.Topics.First().Description)
}
Related
I have two models and I need to display data in my layout page and in every page that the user visit. Those two models have not any relationship between them so I don't need any join.
this is my controller
public ActionResult Index()
{
var notification = (from n in db.Notification
where n.NotificationIsSeen == true
select n);
var task = (from t in db.Task
where t.TaskIsSeen == true
select t);
return View();// I not sure how to return both of queries
}
I also create a model that contains both of them but I 'not sure if this is the right way
public class Layout
{
public Notification Notification { get; set; }
public Task Task { get; set; }
}
and in my layout page
#model IEnumerable<MyprojectName.Models.Layout>
//other code
#foreach (var item in Model)
{
<li>#Html.DisplayFor(modelItem => item.Notification.NotificationSubject ) </li>}
//other code
#foreach (var item in Model)
{
<li>#Html.DisplayFor(modelItem => item.Task.TaskSubject )
</li>
}
I have seen other similar question but they work with join tables.
I need some help on returning data of both tables. thank you in advance
Your queries in your action method both return collections of data. To accommodate this your view model needs to have two lists and needs to look something like this. You have to be able to store these collections in lists when sending them to the view:
public class Layout
{
public IEnumerable<Notification> Notifications { get; set; }
public IEnumerable<Task> Tasks { get; set; }
}
To populate these lists change the code in your action method to this. Create an instance of Layout, populate the two lists and then send the instance to the view:
public ActionResult Index()
{
Layout model = new Layout();
model.Notifications = (from n in db.Notification
where n.NotificationIsSeen == true
select n);
model.Tasks = (from t in db.Task
where t.TaskIsSeen == true
select t);
return View(model);
}
Your view needs to accept and instance of Layout:
#model MyprojectName.Models.Layout
#foreach (var notification in Model.Notifications)
{
<div>
#notification.NotificationSubject
</div>
}
#foreach (var task in Model.Tasks)
{
<div>
#task.TaskSubject
</div>
}
I hope this helps.
Please declare list type of model in you layout model
Layout Model
public class Layout
{
public IEnumerable<Notification> Notifications { get; set; }
public IEnumerable<Task> Tasks { get; set; }
}
Controller
public ActionResult Index()
{
Layout model = new Layout();
model.Notifications = (from n in db.Notification
where n.NotificationIsSeen == true
select n);
model.Tasks = (from t in db.Task
where t.TaskIsSeen == true
select t);
return View(model);
}
View
#model MyprojectName.Models.Layout
#foreach(var item in Model.Notifications)
{
// access your item.propertyname
}
#foreach(var item in Model.Task)
{
// access your item.propertyname
}
Using partial view for build the dynamic header
1 - create action with partial view and display data
2 - go to layout to call this
#Html.partial("Action","Controller")
I have two dropdown lists and two textboxes
Search By: ByHtml.DropDownList("Search1", "Please Select...")
Html.TextBox("searchString1")
Search By: Html.DropDownList("Search2", "Please Select...")
#Html.TextBox("searchString2")
<input type="submit" value="Filter" />
When I make my selection from whichever DDL and type text into the textbox and hit filter my search returns, however after the search the text remains in the textbox, is there a way of clearing it after the search so that the textbox is empty again? I tried
ModelState.Remove("");
but it didn't work.
A sample from My controller code is
public class MainController : Controller
{
private DBEntities db = new DBEntities();
// GET: /Main/
public ActionResult Index(string searchString1, string searchString2, string Search1, string Search2)
{
//Create a Dropdown list
var SearchOptionList = new List<string>();
SearchOptionList.Add("LandLord");
SearchOptionList.Add("Postcode");
SearchOptionList.Add("Street Address");
ViewBag.Search1 = new SelectList(SearchOptionList);
ViewBag.Search2 = new SelectList(SearchOptionList);
var mylist = from m in "mydatabase" select m;
//This statement runs if the user selects a parameter from Search2 and leaves Search1 empty
if (String.IsNullOrEmpty(Search1) && !String.IsNullOrEmpty(Search2))
{
if (Search2 == "Postcode")
{
mylist = mylist.Where(s => s.Postcode.Contains(searchString2));
}
if (Search2 == "LandLord")
{
mylist = mylist.Where(s => s.Name.Contains(searchString2));
}
if (Search2 == "Street Address")
{
mylist = mylist.Where(s => s.StreetAddress.Contains(searchString2));
}
}
return View(mylist.ToList());
}
Your should have a view model containing properties searchString1 and searchString2 and the select lists
public class SearchVM
{
public string searchString1 { get; set; }
public string searchString2 { get; set; }
public SelectList SearchList1 { get; set; }
public SelectList SearchList2 { get; set; }
}
Controller
public ActionResult Search()
{
SearchVM model = new SearchVM();
model.SearchList1 = new SelctList(...);
model.SearchList2 = new SelctList(...);
return View(model);
}
View
#model SearchVM
#using(Html.BeginForm())
{
....
#Html.DropDownListFor(m => m.searchString1, Model.SearchList1, "--Please select--")
#Html.DropDownListFor(m => m.searchString2, Model.SearchList2, "--Please select--")
....
}
Post
[HttpPost]
public ActionResult Search(SearchVM model)
{
// to clear all modelstate and reset values
ModelState.Clear();
model.searchString1 = null;
model.searchString2 = null;
// or to clear just one property and reset it
ModelState.Remove("searchString1");
model.searchString1 = null;
// repopulate select lists if your returning the view
return View(model);
}
At the end of my public ActionResult Index method but before return View() I placed the following code which worked perfectly
ModelState.Remove("searchString1");
ModelState.Remove("searchString2");
ModelState.Remove("Search1");
ModelState.Remove("Search2");
I know is an old question, but I fall in the same issue. So I put my solution.
View:
#Html.TextBox("Search", null, new { #autofocus = "autofocus" })
Controller:
ViewBag.Search= null;
ModelState.Remove("Search");
return View(list.ToList());
Hope to help someone
I am new to mvc4 so please go easy, i am trying to pass multiple names of destinations from the controller to my view. How can i do this without creating more actionresults and objects. I want to create a table with the destination names using a string array. Is this possible any help would be appreciated. Thank You in advance.
Controller:
public ActionResult Destinations()
{
string[] arrivalAirport = new string[4] { "london", "paris", "berlin",
"manchester" };
Destination dest = new Destination();
dest.arrivalName = arrivalAirport[2];
return View(dest);
}
Model:
public class Destination
{
public string arrivalName { get; set; }
public string arrivalCode { get; set; }
}
View:
#model Flight.Models.Destination
#{
ViewBag.Title = "Destinations";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table>
<tr>
<td>#Html.Label("Arrival Name")</td>
<td>#Model.arrivalName</td>
</tr>
</table>
The wording of your question is very confusing, but it sounds like you want to pass multiple Destination objects to your view. If that's the case, just pass multiple destination objects to your view.
Controller:
public ActionResult Destinations()
{
string[] arrivalAirport = new string[4] { "london", "paris", "berlin",
"manchester" };
var airports = new List<Destination>();
foreach( var airport in arrivalAirport )
{
airports.Add( new Destination() { arrivalName = airport } );
}
return View(airports);
}
View:
#model List<Flight.Models.Destination>
<table>
#foreach( var dest in Model )
{
<tr>
<td>Arrival Name</td>
<td>#dest.arrivalName</td>
</tr>
}
</table>
use a view model where you can define whatever information you need for your view
public class ViewModel{
public List<string> Airports { get; set; }
public Destination destination { get; set; }
etc...
}
then on your controller you populate the view model
public ActionResult Index(){
ViewModel vm = new ViewModel();
var db = //query your database
vm.Destination.arrivalName = db.ArrivalName;
etc...
return View(vm);
}
and on your view
#model ViewModel
#Html.TextBoxFor(x => x.Destination.arrivalName)
Hopefully this helps
I tried searching and didn't find anything that fixed my problem. I have a DropDownList on a Razor view that will not show the the item that I have marked as Selected in the SelectList. Here is the controller code that populates the list:
var statuses = new SelectList(db.OrderStatuses, "ID", "Name", order.Status.ID.ToString());
ViewBag.Statuses = statuses;
return View(vm);
Here is the View code:
<div class="display-label">
Order Status</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.StatusID)
</div>
I walk through it and even in the view it has the correct SelectedValue however the DDL always shows the first item in the list regardless of the selected value. Can anyone point out what I am doing wrong to get the DDL to default to the SelectValue?
The last argument of the SelectList constructor (in which you hope to be able to pass the selected value id) is ignored because the DropDownListFor helper uses the lambda expression you passed as first argument and uses the value of the specific property.
So here's the ugly way to do that:
Model:
public class MyModel
{
public int StatusID { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
ViewBag.Statuses = statuses;
var model = new MyModel();
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
and here's the correct way, using real view model:
Model
public class MyModel
{
public int StatusID { get; set; }
public IEnumerable<SelectListItem> Statuses { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
var model = new MyModel();
model.Statuses = statuses;
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, Model.Statuses)
Make Sure that your return Selection Value is a String and not and int when you declare it in your model.
Example:
public class MyModel
{
public string StatusID { get; set; }
}
Create a view model for each view. Doing it this way you will only include what is needed on the screen. As I don't know where you are using this code, let us assume that you have a Create view to add a new order.
Create a new view model for your Create view:
public class OrderCreateViewModel
{
// Include other properties if needed, these are just for demo purposes
// This is the unique identifier of your order status,
// i.e. foreign key in your order table
public int OrderStatusId { get; set; }
// This is a list of all your order statuses populated from your order status table
public IEnumerable<OrderStatus> OrderStatuses { get; set; }
}
Order status class:
public class OrderStatus
{
public int Id { get; set; }
public string Name { get; set; }
}
In your Create view you would have the following:
#model MyProject.ViewModels.OrderCreateViewModel
#using (Html.BeginForm())
{
<table>
<tr>
<td><b>Order Status:</b></td>
<td>
#Html.DropDownListFor(x => x.OrderStatusId,
new SelectList(Model.OrderStatuses, "Id", "Name", Model.OrderStatusId),
"-- Select --"
)
#Html.ValidationMessageFor(x => x.OrderStatusId)
</td>
</tr>
</table>
<!-- Add other HTML controls if required and your submit button -->
}
Your Create action methods:
public ActionResult Create()
{
OrderCreateViewModel viewModel = new OrderCreateViewModel
{
// Here you do database call to populate your dropdown
OrderStatuses = orderStatusService.GetAllOrderStatuses()
};
return View(viewModel);
}
[HttpPost]
public ActionResult Create(OrderCreateViewModel viewModel)
{
// Check that viewModel is not null
if (!ModelState.IsValid)
{
viewModel.OrderStatuses = orderStatusService.GetAllOrderStatuses();
return View(viewModel);
}
// Mapping
// Insert order into database
// Return the view where you need to be
}
This will persist your selections when you click the submit button and is redirected back to the create view for error handling.
I hope this helps.
For me, the issue was caused by big css padding numbers ( top & bottom padding inside the dropdown field). Basically, the item was being shown but not visible because it was way down. I FIXED it by making my padding numbers smaller.
I leave this in case it helps someone else. I had a very similar problem and none of the answers helped.
I had a property in my ViewData with the same name as the selector for the lambda expression, basically as if you would've had ViewData["StatusId"] set to something.
After I changed the name of the anonymous property in the ViewData the DropDownList helper worked as expected.
Weird though.
My solution was this...
Where the current selected item is the ProjectManagerID.
View:
#Html.DropDownList("ProjectManagerID", Model.DropDownListProjectManager, new { #class = "form-control" })
Model:
public class ClsDropDownCollection
{
public List<SelectListItem> DropDownListProjectManager { get; set; }
public Guid ProjectManagerID { get; set; }
}
Generate dropdown:
public List<SelectListItem> ProjectManagerDropdown()
{
List<SelectListItem> dropDown = new List<SelectListItem>();
SelectListItem listItem = new SelectListItem();
List<ClsProjectManager> tempList = bc.GetAllProductManagers();
foreach (ClsProjectManager item in tempList)
{
listItem = new SelectListItem();
listItem.Text = item.ProjectManagerName;
listItem.Value = item.ProjectManagerID.ToString();
dropDown.Add(listItem);
}
return dropDown;
}
Please find sample code below.
public class Temp
{
public int id { get; set; }
public string valueString { get; set; }
}
Controller
public ActionResult Index()
{
// Assuming here that you have written a method which will return the list of Temp objects.
List<Temp> temps = GetList();
var tempData = new SelectList(temps, "id", "valueString",3);
ViewBag.Statuses = tempData;
return View();
}
View
#Html.DropDownListFor(model => model.id, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.id)
I'm kind of new to razor MVC, and I'm wondering how can I read the values I return in the view?
My code is like this:
public ActionResult Subject(int Category)
{
var db = new KnowledgeDBEntities();
var category = db.categories.Single(c => c.category_id == Category).name;
var items = from i in db.category_items
where i.category_id == Category
select new { ID = i.category_id, Name = i.name };
var entries = from e in db.item_entry
where items.Any(item => item.ID == e.category_item_id)
select new { ID = e.category_item_id, e.title };
db.Dispose();
var model = new { Name = category, Items = items, Entries = entries };
return View(model);
}
Basically, I return an anonymous type, what code do I have to write to read the values of the anonymous type in my view?
And if this is not possible, what would be the appropriate alternative?
Basically, I return an anonymous type
Nope. Ain't gonna work. Anonymous types are emitted as internal by the compiler and since ASP.NET compiles your views into separate assemblies at runtime they cannot access those anonymous types which live in the assembly that has defined them.
In a properly designed ASP.NET MVC application you work with view models. So you start by defining some:
public class MyViewModel
{
public string CategoryName { get; set; }
public IEnumerable<ItemViewModel> Items { get; set; }
public IEnumerable<EntryViewModel> Entries { get; set; }
}
public class ItemViewModel
{
public int ID { get; set; }
public string Name { get; set; }
}
public class EntryViewModel
{
public int ID { get; set; }
public string Title { get; set; }
}
and then you adapt your controller action to pass this view model to the view:
public ActionResult Subject(int Category)
{
using (var db = new KnowledgeDBEntities())
{
var category = db.categories.Single(c => c.category_id == Category).name;
var items =
from i in db.category_items
where i.category_id == Category
select new ItemViewModel
{
ID = i.category_id,
Name = i.name
};
var entries =
from e in db.item_entry
where items.Any(item => item.ID == e.category_item_id)
select new EntryViewModel
{
ID = e.category_item_id,
Title = e.title
};
var model = new MyViewModel
{
CategoryName = category,
Items = items.ToList(), // be eager
Entries = entries.ToList() // be eager
};
return View(model);
}
}
and finally you strongly type your view to the view model you have defined:
#model MyViewModel
#Model.Name
<h2>Items:</h2>
#foreach (var item in Model.Items)
{
<div>#item.Name</div>
}
<h2>Entries:</h2>
#foreach (var entry in Model.Entries)
{
<div>#entry.Title</div>
}
By the way to ease the mapping between your domain models and view models I would recommend you checking out AutoMapper.
Oh, and since writing foreach loops in a view is kinda ugly and not reusable I would recommend you using display/editor templates which would basically make you view look like this:
#model MyViewModel
#Model.Name
<h2>Items:</h2>
#Html.DisplayFor(x => x.Items)
<h2>Entries:</h2>
#Html.DisplayFor(x => x.Entries)
and then you would define the respective display templates which will be automatically rendered for each element of the respective collections:
~/Views/Shared/DisplayTemplates/ItemViewModel:
#model ItemViewModel
<div>#item.Name</div>
and ~/Views/Shared/DisplayTemplates/EntryViewModel:
#model EntryViewModel
<div>#item.Title</div>