I want to view the table in Edit.cshtml
I was using the Html.Action to get the table from SurveyQuestionController but it shows the error as below:
The model item passed into the dictionary is of type 'System.Collections.Generic.List``1[System.String]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[SurveyTool.Models.SurveyQuestionModel]'.
Anything that i'm wrong??
Edit.cshtml:
#model SurveyTool.Models.SurveyModel
<div>
<h2>Link</h2>
#Html.Action("QuestionLink", "SurveyQuestion", new { id = Model.SurveyID })
</div>
SurveyQuestionController.cs:
public ActionResult QuestionLink(string SurveyID)
{
var query = (from r in db.SurveyQuestionModels
where r.SurveyId == SurveyID
select r.QuestionLink).Distinct();
return PartialView(query.ToList());
}
QuestionLink.cshtml :
#model IEnumerable<SurveyTool.Models.SurveyQuestionModel>
<br />
<table class="strip">
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelitem => item.QuestionLink)</td>
</tr>
}
</table>
SurveyQuestionModel.cs :
namespace SurveyTool.Models
{
public class SurveyQuestionModel
{
public int Id { get; set; }
public string QuestionLink { get; set; }
}
}
You query is selecting only the QuestionLink property of SurveyQuestionModel (by you use select r.QuestionLink) which is typeof string, hence your returning List<string> to the view, when the view expects List<SurveyQuestionModel>
Change the query to return a collection of SurveyQuestionModel
public ActionResult QuestionLink(string SurveyID)
{
var query = (from r in db.SurveyQuestionModels
where r.SurveyId == SurveyID
select r);
return PartialView(query.ToList());
}
or change the view so the model is List<string>
#model List<string>
#foreach (var item in Model)
{
#Html.DisplayFor(modelitem => item)
}
Related
I'm trying to make a table with 2 rows of headers, both of them update dynamically from 2 separate database tables. The content update part is ok, it works. The problem is, the cells in the first row must span over whatever the number of entries of that particular category is in the 2nd row.
I've grouped the second row categories by elements with their id, counted the ids and put them in a ViewBag.
The first row model:
[Table("categories")]
public class CategoriesModel
{
[Column("category_id")]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Required]
public int CategoryId { get; set; }
[Column("category_name")]
//[Required]
public string CategoryName { get; set; }
}
Second row model:
[Table("materials")]
public class MaterialModel
{
[Column("material_id")]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Required]
public int MaterialId { get; set; }
[Column("height_x_width")]
[Required]
public string Dimensions { get; set; }
[Column("category_id")]
[Required]
public int CategoryId { get; set; }
public List<CategoriesModel> MaterialCategory { get; set; }
}
The ViewModel:
public class NationalCampaignViewModel
{
public string Campaign { get; set; }
public IEnumerable<RestaurantModel> Restaurant { get; set; }
public IEnumerable<CategoriesModel> Categories { get; set; }
public IEnumerable<MaterialModel> Materials { get; set; }
public IEnumerable<OptionModel> Options { get; set; }
}
the ViewModelController:
public class NationalCampaignViewModelController : Controller
{
private readonly McDdbContext _context;
public NationalCampaignViewModelController(McDdbContext context)
{
_context = context;
}
// GET: NationalCampaign
public async Task<IActionResult> Index(int? id)
{
var campaign = await _context.NationalCampaigns.FirstOrDefaultAsync(m => m.Id == id);
var restaurant = await _context.Restaurants.ToListAsync();
//var stl = await _context.STL.ToListAsync();
//var dtl = await _context.DTL.ToListAsync();
var categories = await _context.CategoriesModel.ToListAsync();
var options = await _context.OptionModel.ToListAsync();
var materials = await _context.MaterialModel.ToListAsync();
var colSpan = materials.OrderBy(x => x.CategoryId).GroupBy(x => x.CategoryId).ToDictionary(g => g.Key, g => g.Count());
ViewBag.ColSpan = colSpan.Values;
var tables = new NationalCampaignViewModel
{
Campaign = campaign.CampaignName,
Restaurant = from r in restaurant select r,
Categories = from c in categories orderby c.CategoryId select c,
//Options = from o in options select o,
Materials = from m in materials orderby m.CategoryId select m
};
if (id == null)
{
return NotFound();
}
return View(tables);
}
The View:
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>#Model.Campaign</h1>
<div class="container">
<div class="row">
<div class="col">
<table class="table-bordered">
#foreach (var span in ViewBag.ColSpan)
{
<colgroup>
<col span="#span" />
</colgroup>
}
<thead>
<tr align="center">
<th>#Html.DisplayNameFor(model => model.Restaurant.FirstOrDefault().Restaurant_Name)</th>
#foreach (var c in Model.Categories)
{
<th scope="colgroup">#c.CategoryName</th>
}
</tr>
<tr>
<th>Dimensions</th>
#foreach (var m in Model.Materials)
{
<th>#m.Dimensions</th>
}
</tr>
</thead>
<tbody>
#*#foreach (var item in Model.Restaurant)
{
<tr>
<td>
<a asp-controller="Restaurant" asp-action="Edit"
asp-route-id="#item.Restaurant_Id">#Html.DisplayFor(modelItem => item.Restaurant_Name)</a>
</td>
</tr>
}*#
</tbody>
</table>
</div>
The table with the number of columns to span over:
Solved it with dictionary.
Controller:
var colSpan = materials.OrderBy(x => x.CategoryId).GroupBy(x => x.CategoryId).ToDictionary(g => g.Key, g => g.Count());
Dictionary<string, int> headerValues = new Dictionary<string, int>();
List<string> keys = new List<string>();
foreach (var category in categories)
{
keys.Add(category.CategoryName);
}
headerValues = keys.Zip(colSpan.Values, (k, v) => new { k, v })
.ToDictionary(x => x.k, x => x.v);
ViewBag.ColSpan = headerValues;
View:
#foreach (var item in ViewBag.Colspan)
{
<th colspan="#item.Value">#item.Key</th>
}
I got to list all the users by using this in my controller:
public IActionResult ListUsers(){
var users = _application.Users.ToList();
return View(users);
}
but i can't seem to be able to add the ROLE field from the aspnetroles table.. It should be a simple join but every attempt i have tried failed, like this one:
public async Task<IActionResult> Edit(string id)
{
var applicationUser = await _context.ApplicationUser.SingleOrDefaultAsync(m => m.Id == id);
var model = new UsuariosViewModel
{
CC = applicationUser.CC,
Apellido = applicationUser.Apellido,
Nombre = applicationUser.Nombre,
Rol = await _userManager.GetRolesAsync(applicationUser)
};
return View(model);
}
how should the method look like?
And also, how should the view look like after the join?
User may has more than one role
This is action:
public async Task<IActionResult> UsersRolesList()
{
var AllUsers = _application.Users.ToList();
UsersAndRolesViewModel UserAndRoleViewModel = new UsersAndRolesViewModel();
List<UserAndRoleViewModel> AllUsersAndRoles = new List<UserAndRoleViewModel>();
foreach (var usr in AllUsers)
{
var model = new UserAndRoleViewModel
{
UserName = usr.UserName,
Roles = await userManager.GetRolesAsync(usr)
};
AllUsersAndRoles.Add(model);
}
UserAndRoleViewModel.UserAndRole = AllUsersAndRoles;
return View(UserAndRoleViewModel);
}
and this view:
#model UsersAndRolesViewModel
<table style="width:100%">
#foreach (var usr in Model.UserAndRole)
{
<tr>
<td>
UserName:
#usr.UserName
</td>
<td>
Roles:
<table>
<tr>
#foreach (var role in usr.Roles)
{
<td>
Role Name: #role
</td>
}
</tr>
</table>
</td>
</tr>
}
</table>
this is ViewModel
public class UserAndRoleViewModel
{
public string UserName { get; set; }
public IList<string> Roles { get; set; }
}
public class UsersAndRolesViewModel
{
public List<UserAndRoleViewModel> UserAndRole { get; set; }
}
<table>
#foreach (DataRow row in Model.Rows)
{
<tr>
#foreach (DataColumn col in Model.Columns)
{
<td>#row[col.ColumnName]</td>
}
</tr>
}
</table>
#Html.ActionLink("Pass", "Insert", "Home")
When clicking the pass link i would like the columns to be inserted into db. Is there any tutorial on how to do this?
Please try this sample.
Create a view model class as follows
public class DataRows
{
public int Column1{ get; set; }
public string Column2 { get; set; }
public double Column3 { get; set; }
}
public class MyModel
{
public virtual DataRows[] DataSet { get; set; }
}
Retrieve all the data using your business logic into MyModel in your controller. I am demonstrating this using a sample code
public TestModel GenerateModel()
{
var model = new TestModel();
model.DataSet = this.GenerateDataGridData().ToArray();
return model;
}
private ICollection<SampleDataSet> GenerateDataGridData()
{
var list = new List<SampleDataSet>()
{
new SampleDataSet() { Column1= 1, Column2= "XXX", Column3= 23 },
new SampleDataSet() { Column1= 2, Column2= "YYY", Column3= 27 },
new SampleDataSet() { Column1= 3, Column2= "ZZ", Column3= 25 }
};
return list;
}
In the Action of your view you will be calling GenerateModel method as follows
public ActionResult MyView()
{
var model = this.GenerateModel();
return this.View(model);
}
Now you restructure your MyView page as follows
#model MyModel
#{
int i = 0;
}
#using (Html.BeginForm("Insert", "Home", FormMethod.Post))
{
<table>
<thead>
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
</tr>
</thead>
<tbody>
#foreach (var row in Model.DataSet)
{
<tr>
<th>#row.Column1<span>#Html.HiddenFor(x => Model.DataSet[i].Column1)</span></th>
<th>#row.Column2<span>#Html.HiddenFor(x => Model.DataSet[i].Column2)</span></th>
<th>#row.Column3<span>#Html.HiddenFor(x => Model.DataSet[i].Column3)</span></th>
</tr>
i++;
}
</tbody>
</table>
<input type="submit" value="Pass" />
}
Now on submiting the data in the view will be posted to your Insert Action of Home controller and you can insert into your DB using your logic
I hope this will be a solution for your query.
My code is below:
On page i have a products list with checkbox, code & name of that product.
When selecting multiple checkboxes, on submit click, i need to get the selected checkbox values & save it in the DB.
Product View Model class:
public class ProductVM
{
public ProductVM()
{
this.ProductsList = new List<Product>();
}
public List<Product> ProductsList { get; set; }
public class Product
{
public bool IsSelected { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
}
Product Controller:
[HttpGet]
public ActionResult Edit()
{
var model = new ProductVM();
var product1 = new ProductVM.Product
{
Code = "Product1",
Name = "Apple"
};
var product2 = new ProductVM.Product
{
Code = "Product2",
Name = "Banana"
};
model.ProductsList.Add(Product1);
model.ProductsList.Add(Product2);
return View(model);
}
[HttpPost]
public ActionResult Edit(ProductVM model)
{
if (model.ProductsList.Any(m => m.Selected))
{
//How to get the selected Code & Name here
}
}
Product View:
#model ProductVM
#using(Html.BeginForm())
{
foreach (var item in Model.ProductsList)
{
#Html.CheckBox("IsSelected", item.IsSelected)
#Html.Label(item.Code)
#Html.Label(item.Name)
}
<input type="submit" />
}
First, you need to use for instead of foreach. Otherwise Razor won't generate the proper field names. Second, you need hidden inputs for the Code and Name properties so these will get posted back:
for (var i = 0; i < Model.ProductsList.Count(); i++)
{
#Html.HiddenFor(m => m.ProductsList[i].Code)
#Html.HiddenFor(m => m.ProductsList[i].Name)
<label>
#Html.CheckBoxFor(m => m.ProductsList[i].IsSelected)
#Html.DisplayFor(m => m.ProductsList[i].Code)
#Html.DisplayFor(m => m.ProductsList[i].Name)
</label>
}
To demo my code from my comment to question- You can get idea from it
#foreach (var item in ViewBag.FocusesList)
{
<label>
<input type="checkbox" value="#item.ConfigurationId" name="FocusList" id="FocusList" /> #item.Value.Name
</label>
}
After submit you have all checked values split by comma in Request["FocusList"]
I'm trying to make a view model to show a list of checkboxes. A checkbox will be checked when its ID is found in the database. However, my code is generating an error.
CheckFacilityVN
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace XNet.WebUI.Hotel.ViewModel
{
public class CheckFacilityVM
{
public int FacilityID { get; set; }
public string facilityName { get; set; }
public List<FacilityAvailable> facilityAvailable { get; set; }
}
public class FacilityAvailable
{
public bool isCheck { get; set; }
}
}
My controller
public ActionResult Facility()
{
var htl = _hotelService.ShowRoomFacility(2);
var list = new List<FacilityAvailable>();
foreach (var x in htl)
{
list.Add(new FacilityAvailable { FacilityID = htl.FacilityID, facilityName = htl.FacilityName, isCheck = htl.IsActive });
}
return View();
}
My constructor
public Facility ShowRoomFacility(int HotelID)
{
var x = (from d in db.Facilities
where d.FacilityID == HotelID
select d).FirstOrDefault();
return x;
}
How can I make these checkboxes?
Start by adapting your view model:
public class CheckFacilityVM
{
public int FacilityID { get; set; }
public string FacilityName { get; set; }
public bool IsFacilityAvailable { get; set; }
}
and then use this view model:
public ActionResult Facility()
{
var model = _hotelService
.ShowRoomFacility(2)
.Select(htl => new CheckFacilityVM
{
FacilityID = html.FacilityID,
FacilityName = html.FacilityName,
IsFacilityAvailable = htl.IsActive,
})
.ToList();
return View(model);
}
and then write a corresponding view:
#model List<CheckFacilityVM>
#using (Html.BeginForm())
{
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Is available</th>
</tr>
</thead>
<tbody>
#for (var i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(x => x[i].FacilityID)
#Html.HiddenFor(x => x[i].FacilityID)
</td>
<td>
#Html.DisplayFor(x => x[i].FacilityName)
#Html.HiddenFor(x => x[i].FacilityName)
</td>
<td>
#Html.CheckBoxFor(x => x[i].IsFacilityAvailable)
</td>
</tr>
}
</tbody>
</table>
<button type="submit">Save</button>
}
and finally:
[HttpPost]
public ActionResult Facility(List<CheckFacilityVM> model)
{
// process the values from the view model here ...
}