How to assign multiple models to a single view? - asp.net-mvc

I have a list of cities and a list of countries and both of them I want to have on the view (aspx) file. I'm trying something like this but it's not working:
namespace World.Controllers {
public class WorldController : Controller {
public ActionResult Index() {
List<Country> countryList = new List<Country>();
List<City> cityList = new List<City>();
this.ViewData["CountryList"] = countryList;
this.ViewData["CityList"] = cityList;
this.ViewData["Title"] = "World Contest!";
return this.View();
}
}
}
<table>
<% foreach (Country country in this.ViewData.Model as IEnumerable) { %>
<tr>
<td><%= country.Code %></td>
</tr>
<% } %>
</table>

You need to get the view data you've set by name. I.E.
<table>
<% foreach (Country country in (List<Country>)this.ViewData["CountryList"]) { %>
<tr>
<td><%= country.Code %></td>
</tr>
<% } %>
</table>
But that's not ideal, because it's not strongly typed. What I would suggest is creating a model specific to your view.
public class WorldModel
{
public List<Country> Countries { get; set; }
public List<City> Cities { get; set; }
}
And then creating your view strongly typed as a WorldModel view. Then in your action:
List<Country> countryList = new List<Country>();
List<City> cityList = new List<City>();
WorldModel modelObj = new WorldModel();
modelObj.Cities = cityList;
modelObj.Countries = countryList;
this.ViewData["Title"] = "World Contest!";
return this.View(modelObj);
Just make sure that your view is strongly typed:
public partial class Index : ViewPage<WorldModel>
And you'll be able to do it this way:
<table>
<% foreach (Country country in ViewData.Model.Countries) { %>
<tr>
<td><%= country.Code %></td>
</tr>
<% } %>
</table>

Related

partial view in mvc core

I would like to sum table column for view model is
public class ColumnTotal {
public int ID { get; set; }
public decimal ColumnOne { get; set; }
public decimal ColumnTwo { get; set; }
public decimal ColumnThree { get; set; }
}
My home controller of columntotal method looks like this
public IActionResult ColumnTotal()
{
var query = _context.REHPData.Include(r => r.BudgetYear).GroupBy(r => r.BudgetYearlyAllocation.ID).Select(s => new ColumnTotal
{
ID = s.Key,
ColumnOne = s.Sum(x => x.BudgetYearlyAllocation.AdminThaTeen),
ColumnTwo = s.Sum(x => x.BudgetYearlyAllocation.AdminThaTwo),
ColumnThree = s.Sum(x => x.BudgetYearlyAllocation.AdminThaFour)
}).ToList();
return View(query);
}
MY partial view _test.cshtml looks like this
#model RenewableEnergyProjcet.Models.CalculationViewModels.ColumnTotal
<tr>
<td> #Html.DisplayFor(m=>m.ColumnOne)</td>
<td> #Html.DisplayFor(m=>m.ColumnTwo)</td>
<td> #Html.DisplayFor(m=>m.ColumnThree)</td>
</tr>
my report.chtml looks like this
#{
ViewData["Title"] = "Budget Result Table ";
}
<h2>Budgets Result Table </h2>
<table class="table table-bordered table-condensed table-responsive table-hover">
<tr>
<td>Some Columns -----</td>
</tr>
#foreach (var item in Model)
{
<tr>
some data----
</tr>
}
<tr>
#await Html.PartialAsync("_test"); //how to call this partial _test.chtml
</tr>
</table>
please how to call partial _test.chtml from in method.
In Action that fill report.chtml call too the query that you use in ColumnTotal() action and send it to the view and in the view use RenderPartial() to call the view.
public IActionResult report()
{
ViewData["ColumnTotal"] = _context.REHPData.Include(r => r.BudgetYear).GroupBy(r => r.BudgetYearlyAllocation.ID).Select(s => new ColumnTotal
{
ID = s.Key,
ColumnOne = s.Sum(x => x.BudgetYearlyAllocation.AdminThaTeen),
ColumnTwo = s.Sum(x => x.BudgetYearlyAllocation.AdminThaTwo),
ColumnThree = s.Sum(x => x.BudgetYearlyAllocation.AdminThaFour)
}).ToList();
return View("report");
}
An in the view do something like this.
#Html.RenderPartial("_test",ViewData["ColumnTotal"])

How to send the value of a dropdownlist along with the model?

I have a view that displays user names with groups they are part of.
In case i switch the group of a user, how can i send bot the user and the new group to the controller ?
View :
<table>
<tr>
<td>user ID</td>
<td>user group</td>
<td>Actions</td>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#item.UserName</td>
<td>#Html.DropDownList("grup", new SelectList(ViewBag.GroupList, "ID", "UserGroupName"), item.UserGroupName)</td>
<td>#Html.ActionLink("Save","EditUserGroup", UserInGroup)</td>
</tr>
}
</table>
Viewbag.GroupList is a list of {ID, GroupName}
Controller
public ActionResult EditUserGroup(UserInGroup userInGroup, string grup)
{
}
How can i send the value of the selected group and the user with all the details ?
Edit
I changed the Model to :
public class UserInGroupModel
{
public IList<UserInGroup> userInGroupList { get; set; }
public int GroupId { get; set; }
}
Controller
public ActionResult UserGroup()
{
IUserGroupService userGroupService = new UserGroupService();
ViewBag.GroupList = userGroupService.GetEntities();
var lista = userInGroupService.GetEntities();
UserInGroupModel userInGroupModel = new UserInGroupModel();
userInGroupModel.userInGroupList = lista;
return View(userInGroupModel);
}
View:
#using (Html.BeginForm("EditUserGroup", "Admin"))
{
<table>
<tr>
<td>user ID</td>
<td>user group</td>
<td>Actions</td>
</tr>
#foreach (var item in Model.userInGroupList)
{
<tr>
<td>#item.UserName</td>
<td>#Html.DropDownListFor(model => model.GroupId, new SelectList(ViewBag.GroupList, "ID", "UserGroupName"))</td>
<td><input type="submit" value="Save"/></td>
</tr>
}
</table>
}
I still cannot send the value of the UserInGroup. I can get the GroupId in the groupId parameter of the controller but, the UserInModel entity is not passed. Can you help me ?
use dropdownlistfor
#Html.DropDownListFor(x => x.grup, new SelectList(ViewBag.GroupList, "ID"...
add a variable to your model for the selected item (grup in this case)

How to create an input box (textbox) for a property of a model

I have a simple shopping cart model which contains a list of items:
public class ShoppingCart
{
public List<Item> Items { get; set; }
public double Tax { get; set; }
// ... some other properties
}
public class Item
{
public string Name { get; set; }
public int Quantity { get; set; }
public double Price { get; set; }
public double TotalCost { get { return Quantity * Price; } }
}
I want to modify the quantity of a particular item and I've made the following View:
<%using (Html.BeginForm("Recalculate", "ShoppingCart", Model))
{ %>
<table id="cartTable" border ="5px" cellpadding="5px" cellspacing="5px" width="640">
<tr>
<td><b>Item Name</b></td>
<td><b>Item Qty</b></td>
<td><b>Item Price</b></td>
<td><b>Subtotal</b></td>
</tr>
<%
if (Model != null && Model.Items != null)
{
foreach (ShoppingCart.Models.Item item in Model.Items)
{
%>
<tr>
<td><%: item.Name%></td>
<td><%: Html.TextBoxFor(m => m.Items[Model.Items.IndexOf(item)], new { #Value = item.Quantity })%></td>
<td><%: String.Format("{0:C}", item.Price)%></td>
<td><%: String.Format("{0:C}", item.TotalCost)%></td>
</tr>
<%
}
}
%>
<!-- some other rows/columns go here -->
</table>
<input type="submit" value="Update Cart" />
<%} %>
And my controller:
public class ShoppingCartController : Controller
{
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult Show(ShoppingCart model)
{
if (model!= null && model.Items == null)
{
List<Item> items = new List<Item>();
items.Add(new Item { Name = "Hat", Price = 20.0, Quantity = 1 });
items.Add(new Item { Name = "Snowboard", Price = 430.0, Quantity = 1 });
items.Add(new Item { Name = "Goggles", Price = 24.0, Quantity = 3 });
model.Items = items;
model.Tax = 6.5;
}
return View(model);
}
[HttpPost]
public ActionResult Recalculate(ShoppingCart model)
{
if (model != null && model.Items!=null)
{
foreach (Item item in model.Items)
{
if (item.Quantity == 0)
{
model.Items.Remove(item);
}
else if (item.Quantity < 0)
{
ModelState.AddModelError("error", "The quantity for " + item.Name + " must not be smaller than 0.");
}
}
}
return RedirectToAction("Show", "ShoppingCart", model);
}
}
Unfortunately when I click on the Update Cart button it calls my Recalculate function, but now all of the items in the Items list are null. How can I keep the items AND update the quantity of a given item?
In the BeginForm function I tried passing in the current model and not passing it a model at all... nothing changes. Could anybody help me figure this out?
Do these changes in appropriate locations and things would start working. Note that while the postback the Price and TotalCost would not be populated in the model as the corresponding rendered items are static text. These can be repopulated in the Controller or add hidden field in the view so that these can be posted and repopulated.
<%using (Html.BeginForm("Recalculate", "ShoppingCart", FormMethod.Post))
<td><%: Html.TextBoxFor(m => m.Items[Model.Items.IndexOf(item)].Quantity)%></td>
//return RedirectToAction("Show", "ShoppingCart", model);
return View("Show", model);
<%= Html.TextBox("Quantity", Model.Items[Model.Items.IndexOf(item)].Quantity ) %>
This is a nice blog post, worth a read: http://weblogs.asp.net/nmarun/archive/2010/03/13/asp-net-mvc-2-model-binding-for-a-collection.aspx

Display a view with many to many relationship

Having problem to display a generic list with books and its authors at view state.
A book can have one, two or three authors.
How shall I display a list that contains many books with right authors in view level?
// Fullmetalboy
The following tables of the database is:
Bok (eng. Book)
BokID
Titel
Styckpris
Sammanfattning
Bok_Forfattare (eng. Book_Author)
Bok_ForfattareID
BokID
ForfattareID
Forfattare (eng. Author)
ForfattareID
Fornamn
Efternamn
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<BokButik1.ViewModels.SokningPerformSearchViewModel>"
%>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent"
runat="server">
PerformSearch
<h2>Sökresultat</h2>
<table>
<% foreach (var bok in Model.Boks) { %>
<tr>
<td><%: bok.Titel %> av <%: bok.Bok_Forfattare %></td>
<td rowspan="2"><%: bok.Kategori.KategoriNamn %></td>
<td rowspan="2"><div id="Div1"><input type="submit"
value="+ Add to cart" />
<%: bok.Sammanfattning %>
..
<% } %>
</table>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult PerformSearch(string txtSearch, Kategori kategoriNummer)
{
Search test = new Search(txtSearch, kategoriNummer);
var asdf = test.HamtaBokListaFranSokFunktion();
var results = new SokningPerformSearchViewModel
{
Boks = asdf,
Bok_Forfattares = myIBok_ForfattareRepository.HamtaAllaBok_ForfattareNummer()
};
return View(results);
}
namespace BokButik1.ViewModels
{
public class SokningPerformSearchViewModel
{
public List<Bok> Boks { get; set; }
public List<Bok_Forfattare> Bok_Forfattares { get; set; }
}
}
I would split your ViewModel into two ViewModels:
public class SokningPerformSearchViewModel
{
public IList<BookSearchResultViewModel> Boks { get; set; }
}
public class BookSearchResultViewModel
{
public IList<Bok> Boks { get; set; }
public IList<Bok_Forfattare> Bok_Forfattares { get; set; }
}
For every book returned in the search results, create a new BookSearchResultViewModel and assign the book to Boks. Then fetch the authors and attach them to Bok_Forfattares. Next, add that book into your SokningPerformSearchViewModel.Boks list. Finally, return the SokningPerformSearchViewModel to your View.

Asp.Net Mvc - RenderAction - Create in a list view

EDIT
I put my solution on a share site. Like that you'll be able to see what I'm talking about. You can download it here : http://www.easy-share.com/1909069597/TestRenderAction.zip
To test it, start the project (let the create form empty) and click the Create button. You'll see what happen.
It's only a example project. I don't care to persist my object to the database for now. I care to make my example work.
I got the following controller :
public class ProductController : Controller
{
public ActionResult List()
{
IList<Product> products = new List<Product>();
products.Add(new Product() { Id = 1, Name = "A", Price = 22.3 });
products.Add(new Product() { Id = 2, Name = "B", Price = 11.4 });
products.Add(new Product() { Id = 3, Name = "C", Price = 26.5 });
products.Add(new Product() { Id = 4, Name = "D", Price = 45.0 });
products.Add(new Product() { Id = 5, Name = "E", Price = 87.79 });
return View(products);
}
public ViewResult Create()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
return View(product);
}
}
The following model :
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
My Product/List.aspx :
<h2>List</h2>
<table>
<tr>
<th></th>
<th>
Id
</th>
<th>
Name
</th>
<th>
Price
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
<%= Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%>
</td>
<td>
<%= Html.Encode(item.Id) %>
</td>
<td>
<%= Html.Encode(item.Name) %>
</td>
<td>
<%= Html.Encode(String.Format("{0:F}", item.Price)) %>
</td>
</tr>
<% } %>
</table>
<p>
<% Html.RenderAction("Create"); %>
</p>
My Product/Create.ascx :
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm("Create", "Product", FormMethod.Post)) {%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="Id">Id:</label>
<%= Html.TextBox("Id") %>
<%= Html.ValidationMessage("Id", "*") %>
</p>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %>
</p>
<p>
<label for="Price">Price:</label>
<%= Html.TextBox("Price") %>
<%= Html.ValidationMessage("Price", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
The problem is that when I hit the create button and I got an error (like empty field), the return view only return my Create.ascx control. It's doesn't return the Product/List.asxp page with in my Create.ascx control with the errors. That's what I would like it's does.
Any idea how I can solve that problem ?
I use Asp.Net Mvc 1 with Asp.Net Futures (which have the Html.RenderAction).
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
...
return View("List");
}
or
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
...
return RedirectToAction("List", "Product");
}
your controller should work like this:
public class ProductController : Controller
{
IList<Product> products;
public ProductController( )
{
products = new List<Product>();
products.Add(new Product() { Id = 1, Name = "A", Price = 22.3 });
products.Add(new Product() { Id = 2, Name = "B", Price = 11.4 });
products.Add(new Product() { Id = 3, Name = "C", Price = 26.5 });
products.Add(new Product() { Id = 4, Name = "D", Price = 45.0 });
products.Add(new Product() { Id = 5, Name = "E", Price = 87.79 });
}
public ActionResult List( )
{
return View(products);
}
public ActionResult Create()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
products.Add(product);
return View("List", products);
}
}
Additionally, you need to call RenderPartial instead of RenderAction, because otherwise your POST method will be invoked (due to you did a post-command by submitting the form):
<p>
<% Html.RenderPartial("Create"); %>
</p>
This should work, you only need to persist your products list, as it will reset with every postback.
I hope this helped you :)
Are the names of your text fields the same as the properties in your Product object?
Does your product object declare it's properties like this;
public string Name {get;set;}
You must have getters and setters on your objects.
EDIT
Wait, are you wanting fields from your list View to be available in the post to your create action? If yes then you need to place the BeginForm at the View level and not the PartialView level.
Only fields contained within the begin form will be posted to your controller.
EDIT 2
Ah, I think I see it now.
In your controller I think you should do a product.IsValid to check first.
But in your html you should also do this;
<%= Html.TextBox("Id", Model.Id) %>
You need to fill in the value for the text box.
Hope this is what you were after.

Resources