Viewbag data list won't show in the HTML View - c#

In my ASP.NET MVC application, I'm trying to pass some values from controller to view.
For this, I'm using the view bag method.
From the controller, the data is passed to the view.
In the view within the for each loop, it also shows the data in the view bag.
But when it runs, I'm getting an error 'object' does not contain a definition for 'cusName'
This is the controller
var SuggestionList = (from c in db.tbl_Main
where c.Suggestion != null orderby c.CreatedDate descending select new
{
cusName = c.CustomerName,
Suggest = c.Suggestion
}).Take(3).ToList();
ViewBag.suggestList = SuggestionList;
return View();
In the view
#foreach(var data in ViewBag.suggestList) {
<li > #data.cusName < /li>
}

Would suggest creating a model class (concrete type) and returning it as List<ExampleModel> type instead of an anonymous list.
public class ExampleModel
{
public string CusName { get; set; }
public string Suggest { get; set; }
}
var SuggestionList = (from c in db.tbl_Main
where c.Suggestion != null
orderby c.CreatedDate descending
select new ExampleModel
{
CusName = c.CustomerName,
Suggest = c.Suggestion
})
.Take(3)
.ToList();
ViewBag.suggestList = SuggestionList;
return View();

Related

ASP.NET Core web api serialize an object's List type property

After the server returned the object, the List type field went missing.
Each EmployeeViewModel has a list of EmployeeContactViewModel objects. The intended logic is, after querying the employee object from database, populate the view model in a method, including the list, and return to client.
The view model:
public class EmployeeViewModel
{
public List<EmployeeContactViewModel> EmployeeContacts;
public EmployeeViewModel()
{
EmployeeContacts = new List<EmployeeContactViewModel>();
}
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
// more fields
}
The method to populate view models:
public EmployeeViewModel GetViewModelFromEmpObject()
{
var vm = new EmployeeViewModel();
var contact1 = this.CONTACTs.Where(e => e.ContactId == 1).FirstOrDefault();
if (contact1 != null)
{
var contactVm1 = new EmployeeContactViewModel();
CopyContactFields(contact1, contactVm1); // method to populate view-model
vm.EmployeeContacts.Add(contactVm1);
}
else
vm.EmployeeContacts.Add(new EmployeeContactViewModel());
var contact2 = this.CONTACTs.Where(e => e.ContactId == 2).FirstOrDefault();
if (contact2 != null)
{
var contactVm2 = new EmployeeContactViewModel();
CopyContactFields(contact1, contactVm2); // method to populate view-model
vm.EmployeeContacts.Add(contactVm2);
}
else
vm.EmployeeContacts.Add(new EmployeeContactViewModel());
// more lines below
}
The api controller method is below. By setting a breakpoint at the return line, I could see the EmployeeContactViewModel list was correctly created.
[HttpGet("{empid:string}")]
public async Task<EmployeeViewModel> GetAsync(string empid)
{
Employee emp = await _context.Employees
.Include(c => c.CONTACTs)
.Where(c => c.EmployeeId == empid)
.FirstOrDefaultAsync();
var viewModel = emp.GetViewModelFromEmpObject();
return viewModel;
}
However on the client side, although all the other fields (EmployeeId, EmployeeName, etc.) were present in the response, there was nothing for EmployeeContacts list, when inspecting the server response in the browser network tab.
I tried to search before asking but using "Serialize" as a keyword would just get topics on how to do serialization. Any advice is appreciated.
Do you mean that EmployeeContacts is not included in the response result?
You can install Microsoft.AspNetCore.Mvc.NewtonsoftJson, and add this line in Program.cs:
builder.Services.AddMvc().AddNewtonsoftJson(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

Show buttons on a partial view based on some query

I am showing search results same as searching groups on facebook
enter image description here
I have a relationship Table named CommunityUser in Database having attributes CommunityID and UserID.
Using Partial View I want to show if User not already joined that Community/Group that it will show Join Button else if user already joined that community it will show Leave button.
I have written IsMember() function in my controller that takes two parameters, CommunityID and UserID. This will return true if that Community ID exist against that user ID.
public bool IsMember(string UserID, int CommunityID) {
var Membership = db.Users.Include(x => x.CommunityUsers).Where(s => s.Id.Equals(UserID)).Count();
if(Membership>0)
return true;
else
return false;
}
Now what I actually need is, I want to call this function in an IF condition on my view class. It is not allowing me to call this function on my view Class.
#if (){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
In your controller you should have a method which will return this view. So in this method you call this function
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
return View(hasMembership);
}
In the View it self then you just grab this variable hasMembership you just passed from #model.
#if (Model){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
Note: it might be wise to create some DTO class for passing data to a view, because you might need to pass multiple value to a view at some point. Plus the whole condition would be more readable
public SomeDTO {
public bool IsMember {get;set}
public List<Community> Communities {get;set;}
}
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
var listOfCommunities = _repo.GetComunities();
var dto = new SomeDTO
{
IsMember = hasMembership,
Communities = listOfCommunities
}
return View(dto);
}
#if (Model.IsMember){
// do or do not something
}

Razor looping through Viewbag and bind to it

I have list of objects in my coming from controller.
it looks like this
{ Driver = System.Data.Entity.Driver_Driver1, Statuss = NotConfirmed }
{ Driver = System.Data.Entity.Driver_Driver2, Statuss = NotConfirmed }
please note that Driver is a complex type object.
Controller:
var Drivers = _db.Drivers.Where(x => x.DriverCompanyID == id).Where(d => d.CanWorkIn.Where(f => f.CompanyToDriveFor.CompanyID == OwnCompany.CompanyID).Any())
.Select(x => new
{
Driver = x,
Statuss = x.CanWorkIn.FirstOrDefault().Status.ToString()
}).ToList();
ViewBag.ListOfDrivers = Drivers;
return PartialView("_DriverList");
My Model
public class DriverViewItem
{
public Driver Driver { get; set; }
public string Statuss { get; set; }
}
My View
#model List<MyApp.web.Models.DriverViewItem>
and this last bit does not work. model declaration.
First create a strongly typed class with the properties you require. I've called mine DriverViewItem.
Then in your controller change the select to select this DriverViewItem and parse the list as a model to the view.
var Drivers = _db.Drivers.Where(x => x.DriverCompanyID == id).Where(d => d.CanWorkIn.Where(f => f.CompanyToDriveFor.CompanyID == OwnCompany.CompanyID).Any())
.Select(x => new DriverViewItem()
{
Driver = x,
Statuss = x.CanWorkIn.FirstOrDefault().Status
}).ToList();
return PartialView("_DriverList", Drivers);
In the view you will need to tell the view to expect your model you can do this with:
#model List<DriverViewItem>
Then you can iterate through the items like so:
#foreach(DriverViewItem item in Model)
{
<div>
<p>#item.Driver.{what ever property}</p>
<p>#item.Statuss</p>
</div>
}
This is a much cleaner way than parsing data using the ViewBag.
It would be better to use the model instead to pass this kind of data. But to answer the question directly, in the controller, assign it as an array of items to the viewbag
ViewBag.Data = {
new { Driver = System.Data.Entity.Driver_Driver1, Status = NotConfirmed },
new { Driver = System.Data.Entity.Driver_Driver2, Status = NotConfirmed }
}
And in the markup:
#{
if (ViewBag.Data != null){
foreach (var item in ViewBag.Data) {
//show the item in the view
}
}
}

C# Razor Syntax - html.displayfor displaying as text, not html

My models:
public class htmlDump {
public string html { get; set; }
}
public string getSquares() {
var sq = (from s in n.squares
where s.active == true
orderby s.date_created descending
select s.html).First();
return sq;
}
My controller:
public ActionResult index() {
intranetGS.htmlDump sq = new intranetGS.htmlDump {
html = g.getSquares()
};
return View(sq);
}
My View:
#Html.DisplayFor(model => model.html)
All I want is for the html being passed to the view to be rendered as html and not as text. Surely there's something different I can use in the view (instead of .DisplayFor) that will work. Any suggestions?
Thanks very much!
#Html.Raw(Model.html)
NOTE: if this data can be input by the user - make sure it's sanitized.

mvc3 combobox default selected value

I'm using this approach using viewmodel for manipulating values inside combo boxes. Now, I'm struggle to select as default value actual selected value used in create action, not the first one from combo. I know this is fourth parameter in SelectList but I do not know how to use actual UserGroupId cause it's give me an error when using like these
var model = new UserViewModel
{
UserGroups = new SelectList(GetAllUsers(), "UserId", "Name", UserGroupId)
}
return View(model);
public class UserViewModel
{
public int UserGroupId { get; set; }
public IEnumerable<SelectListItem> UserGroups { get; set; }
}
Like this:
var model = new UserViewModel
{
// preselct an item in the dropdown whose value equals 5
// This means that inside your `GetAllUsers()` collection you must
// have an element with UserId=5 and this element will automatically be
// preselcted. Here you could put any value of course
UserGroupId = 5,
UserGroups = new SelectList(GetAllUsers(), "UserId", "Name")
};
return View(model);
and in your view:
#model UserViewModel
...
#Html.DropDownListFor(x => x.UserGroupId, Model.UserGroups)
As for the 4th parameter, it needs to be an actual instance that is part of the collection returned by GetAllUsers()
For example:
var users = GetAllUsers();
var defaultUser = users[0];
var model = new UserViewModel
{
UserGroups = new SelectList(users, "UserId", "Name", defaultUser)
};
return View(model);
You may want to manually build your SelectList rather than using the SelectList constructor. That will give you the control you need over handling the "UserId" and the "Name". This also addresses the issue of how to add an integer record id to the select list.
Lets start with a method that builds and returns a List<SelectListItem>
public static List<SelectListItem> UserGroups(int userGroupId, int selectedUserId)
{
var userGroupsQuery = from u in dbContext.Users
where u.UserGroupId == userGroupId
select u;
var userSelectList= new List<SelectListItem>();
foreach (var user in userGroupsQuery.Users)
{
userSelectList.Add(
new SelectListItem
{
Text = userGroup.Name,
Value = userGroup.UserId.ToString(CultureInfo.InvariantCulture),
Selected = (user.UserId == selectedUserId)
};
}
return userSelectList;
}
Now we have a select list that we can use so lets use it in our action method.
int selectedUserId = 1000;
int userGroupId = 5;
var userViewModel = new UserViewModel
{
UserGroups = ListLookup.UserGroups(userGroupId, selectedUserId)
}
return View(userViewModel);
And then in the view.
#Html.DropDownList("UserId", Model.Users)
The key here is that the Value property in the select list must be a string, not an integer. Also note that you cannot call to string inside a lambda expression by default (hence the use of a foreach loop). Most SelectList examples do not show how to use the Selected property to select a particular value in the SelectList item.
I hope this helps :)

Categories

Resources