Razor looping through Viewbag and bind to it - c#

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
}
}
}

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;
});

Viewbag data list won't show in the HTML View

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();

How can I capture the #Html.DropDownListFor selected value?

I am using MVC5, Razor, Entity Framework, C#. I am trying to pass a value of a dorpdown list using a link.
my model is
public class TestVM
{
public string TheID { get; set; }
}
I am loading an enum into a IEnumerable<SelectListItem>.
My enum is
public enum DiscountENUM
{
SaleCustomer,
SaleCustomerCategory,
SaleProduct,
SaleProductCategory,
SaleCustomerAndProduct,
SaleCustomerAndProductCategory,
SaleCustomerCategoryAndProductCategory,
PurchaseVendor,
PurchaseVendorAndProduct,
PurchaseVendorAndProductCategory,
PurchaseProduct,
PurchaseProductCategory,
Unknown
}
I am using the index method of the home controller
public ActionResult Index()
{
ViewBag.ListOfDiscounts = SelectListDiscountENUM();
TestVM d = new TestVM();
return View(d);
}
Where I load the ListOfDiscounts using:
private IEnumerable<SelectListItem> SelectListDiscountENUM()
{
List<SelectListItem> selectList = new List<SelectListItem>();
var listOfEnumValues = Enum.GetValues(typeof(DiscountENUM));
if (listOfEnumValues != null)
if (listOfEnumValues.Length > 0)
{
foreach (var item in listOfEnumValues)
{
SelectListItem sVM = new SelectListItem();
sVM.Value = item.ToString();
sVM.Text = Enum.GetName(typeof(DiscountENUM), item).ToString();
selectList.Add(sVM);
}
}
return selectList.OrderBy(x => x.Text).AsEnumerable();
}
My create method which is called from the view is
public ActionResult Create(TestVM d, string TheID)
{
return View();
}
My Index view is
#model ModelsClassLibrary.Models.DiscountNS.TestVM
<div>#Html.ActionLink("Create New", "Create", new { TheID = Model.TheID})</div>
<div>
#Html.DropDownListFor(x => x.TheID, #ViewBag.ListOfDiscounts as IEnumerable<SelectListItem>, "--- Select Discount Type ---", new { #class = "form-control" })
</div>
The problem is in the following line in the View
<div>#Html.ActionLink("Create New", "Create", new { TheID = Model.TheID })</div>
I have tried adding a model with the name of the field as "TheID"... no luck. Also, added a string field in the parameter, no luck. I looked at the FormControl object, and there was nothing in it either! I suspect something has to be added at the Route level in the helper, but I don't know what.
Model.TheID is always null. Even when I select an item in the DropDownListFor.
Does anyone have an idea how I can capture the select value of the DropDownListFor and send it into the Html.ActionLink TheID?

How simplify my request code?

I use this part of code to get informations from my database, using Entity Framework, and add all of it in a IEnumerable property for, at the end, a DropDownListFor display.
I need to use that kind a code many time so I would like to make it the most powerfull at the begenning.
public IEnumerable<SelectListItem> Functions { get
{
List<SelectListItem> result = new List<SelectListItem>();
using (followupconsultantEntities dataModel = new followupconsultantEntities())
{
var myEvents = from e in dataModel.functions
select e;
foreach (var function in myEvents)
{
SelectListItem myList = new SelectListItem
{
Value = function.ID_Function.ToString(CultureInfo.InvariantCulture),
Text = function.FU_Name
};
result.Add(myList);
}
}
return result;
} }
Thanks for help
The view:
<div class="editor-field">
<%: Html.DropDownListFor(m => m.SelectedFunction,Model.Functions) %>
</div>
For information, my controller:
public ActionResult Register()
{
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View(new RegisterModel());
}
Start using System.Web.Mvc.SelectList.
public IEnumerable<SelectListItem> Functions { get
{
using (followupconsultantEntities dataModel = new followupconsultantEntities())
{
return new SelectList(dataModel.functions.ToArray(), "ID_Function", "FU_Name");
}
}
Also consider AutoMapper.
Try this. In this code you will not get from database data that you not need.
public IEnumerable<SelectListItem> Functions { get
{
using (followupconsultantEntities dataModel = new followupconsultantEntities())
{
return new SelectList(dataModel.functions.Select(f=>
new
{
Value = function.ID_Function.ToString(CultureInfo.InvariantCulture),
Text = function.FU_Name
})
.ToArray(), "Value", "Text");
}
}

Convert Dropdownlist item's value to int

I need the value of SelectListItem to be int.
So I pull it of the database, convert it to string in the process and store to listitem's value.
public class BookAdd
{
public BookAdd()
{
public Book Book { get; set; }
DataModelContainer db = new DataModelContainer();
IEnumerable<SelectListItem> items = db.PublisherSet
.Select(i => new SelectListItem
{
Value = SqlFunctions.StringConvert((double)i.Id),
Text = i.Name
});
}
}
I then need to store the value again as int to Book.PublisherId when selected from dropdownlist. I know the code below is not complete, I figured I need somehow convert the selected item's value to int, how do I do it?
#model Bookshops.Models.BookAdd
...
#Html.DropDownListFor(model => model.Book.PublisherId, Model.items);
And finaly controler:
public ActionResult Create2()
{
var bookAdd = new BookAdd();
ViewBag.Publisher = bookAdd.items;
return View(bookAdd);
}
//
// POST: /Book/Create
[HttpPost]
public ActionResult Create2(BookAdd book)
{
if (ModelState.IsValid)
{
Book book2 = new Book();
book2.Id = book.Book.Id;
book2.AuthorId = book.Book.AuthorId;
book2.Isbn = book.Book.Isbn;
book2.Id = int.Parse(book.Book.PubId);
book2.Title = book.Book.Title;
book2.YearPublished = book.Book.YearPublished;
db.BookSet.Add(book2);
db.SaveChanges();
}
return RedirectToAction("Index");
}
I'm using MVC 3, EF 4.
Instead of building a SelectListItem, I built something like this:
public struct BookItem
{
int id;
string name;
}
Then add the following item to the model and select data into it
IEnumerable<BookItem> bookList {get; set;}
Fianally
#Html.DropDownListFor(model => model.Book.PublicherId, new SelectList(Model.bookList, "id", "name"))
When the selected Item of the DropDownList will get posted back convert it to int from string like this Convert.ToInt32(DropDownSelectedItem) or with Int32.TryParse(value, out number)
to start you can simplify the mapping code to
db
.PublisherSet
.Select(x=> new SelectListItem{Value = x.Id.ToString(), Text = x.Name})
.ToArray();
In the view you can then do
#Html.DropDownListFor(model => model.Book.PublisherId, Model.items);
and it will properly render a select element with the options and the appropriate publisher selected.
You can then use the model binding conventions to pass this back to the controller action when the user clicks the submit button.
In the end, it's all text. that's the nature of the web. we have a lot of tricks, converters and binders to turn string dictionaries into rich view models, but ultimately it's just strings.

Categories

Resources