Model MVC IEnumerable without Iteration - c#

Rookie Question. So I have a IEnumerable Model And as you can see my question is simple. I just want to get the Value of the First item in the model Without iterating through the whole model.
As this is only one instance to happen. I don't want to itterate from the model just to get 1 Entity from it and I wouldn't also want to rely on the ViewBag or ViewData for this.
Is this possible?
Client = Model.FirstOrDefault().ClientID
Object reference not set to an instance of an object.
I also tried select()
#model IEnumerable<RMQGrainsFinalCement.ModelsCorn.POCorn>
#{
ViewBag.Title = "POIndex";
}
<h2>PO Index</h2>
#Html.ActionLink("Add PO", "Create", "POCorns", new {ClientID = Model.FirstOrDefault().ClientID },null)

To mitigate unexpected errors, do something like this in your view:
#{
var clientId = 0;
if (Model.Any())
{
clientId = Model.First().ClientId;
}
}
#Html.ActionLink("Add PO", "Create", "POCorns", new {ClientID = clientID },null)

Related

razor dropdown list add the data but show after refresh the page

#{
HotelManagementEntities db = new HotelManagementEntities();
var list = db.tblCategories.Select(m => new { m.intseqid, m.varCategory}).ToList();
ViewBag.Category = new SelectList(db.tblCategories, "intseqid", "varCategory");
}
#Html.DropDownList("tblCategories",
ViewBag.Category as SelectList,
new
{
#class = "drplist",
id = "drpItemCat",
ng_show = "selectfieldforcat"
})
There are problems in your code, you are populating list from database here:
var list = db.tblCategories.Select(m => new { m.intseqid, m.varCategory}).ToList();
but down in the code when creating SelectList, you are again getting records form the database using the dbContext:
ViewBag.Category = new SelectList(db.tblCategories, "intseqid", "varCategory");
// note the db.tblCategories as first parameter, this is wrong
and if you have actually written this code in view, then you don't even need ViewBag, but your approach is not right, you should be writing the poupulation code in the controller action and then use it in the view:
public ActionResult SomeAction()
{
HotelManagementEntities db = new HotelManagementEntities();
ViewBag.Category = new SelectList(db.tblCategories, "intseqid", "varCategory");
}
In Controller:
public ActionResult Add()
{
ViewBag.countryList = GetCountries();
return View();
}
In razor View .csHtml
#Html.DropDownListFor(x => x.countryId, new SelectList(ViewBag.countryList, "id", "Name"), 'Select Country',
new { #id = "ddlCountry", #rows = 1 })
Despite the fact, it's not a good practice to have data retrieval in views, based on you code, you could try the following:
#{
var db = new HotelManagementEntities();
var list = db.tblCategories.Select(m => new
{
m.intseqid,
m.varCategory
}).ToList();
}
#Html.DropDownList("tblCategories", new SelectList(#list, "intseqid", "varCategory"));
A more appropriate approach it would be to create a model, which would contain as a property a SelectList object. Then at the corresponding action at the controller to create a new model and set the categories to mentioned above property. Last pass at your view (so now you have to define that your view expects a model of a specific type, that you declared above) the model and at the dropdownlist html helper do the following:
#Html.DropDownList("tblCategories", Model.Categories)
This way you are more adhered to separation of concerns that is built in the MVC pattern and your code would be more readable and maintainable in the long run. Your example is pretty simple. So that I mentioned before cannot be seen at this point. However, while you model would be more complex and you have to do more things in the views, you will see that I mean by saying more readable and maintainable.
Last but not least, try to avoid using the ViewBag. Apparently you can accomplish what you have to do with the use of ViewBag, but it's far better you pass a strongly typed object as a model to your view and have there all you need to show on the view rather than adding things in the ViewBag at the controller and then use casts in the view to do whatever you want.

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key country

While binding dropdown in MVC, I always get this error: There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key country.
View
#Html.DropDownList("country", (IEnumerable<SelectListItem>)ViewBag.countrydrop,"Select country")
Controller
List<Companyregister> coun = new List<Companyregister>();
coun = ds.getcountry();
List<SelectListItem> item8 = new List<SelectListItem>();
foreach( var c in coun )
{
item8.Add(new SelectListItem
{
Text = c.country,
Value = c.countryid.ToString()
});
}
ViewBag.countrydrop = item8;
return View();
I don't know how to resolve it.
If you were using DropDownListFor like this:
#Html.DropDownListFor(m => m.SelectedItemId, Model.MySelectList)
where MySelectList in the model was a property of type SelectList, this error could be thrown if the property was null.
Avoid this by simply initializing it in constructor, like this:
public MyModel()
{
MySelectList = new SelectList(new List<string>()); // empty list of anything...
}
This often happens in POST actions. Make sure you assign something before re-rendering the view.
In your action change ViewBag.countrydrop = item8 to ViewBag.country = item8;and in View write like this:
#Html.DropDownList("country",
(IEnumerable<SelectListItem>)ViewBag.country,
"Select country")
Actually when you write
#Html.DropDownList("country",
(IEnumerable)ViewBag.country,
"Select country")
or
Html.DropDownList("country","Select Country)
it looks in for IEnumerable<SelectListItem> in ViewBag with key country, you can also use this overload in this case:
#Html.DropDownList("country","Select country") // it will look for ViewBag.country and populates dropdown
See Working DEMO Example
Note that a select list is posted as null, hence your error complains that the viewdata property cannot be found.
Always reinitialize your select list within a POST action.
For further explanation:
Persist SelectList in model on Post
try this
#Html.DropDownList("ddlcountry",(List<SelectListItem>)ViewBag.countrydrop,"Select country")
In Controller
ViewBag.countrydrop = ds.getcountry().Select(x => new SelectListItem { Text = x.country, Value = x.countryid.ToString() }).ToList();
Try This.
Controller:
List<CountryModel> countryList = db.countryTable.ToList();
ViewBag.Country = new SelectList(countryList, "Country", "CountryName");
I had a the same problem and I found the solution that I should put the code to retrieve the drop down list from database in the Edit Method. It worked for me.
Solution for the similar problem
In my case, the error occurred because I had not initialized the select list in the controller like this:
viewModel.MySelectList = new List<System.Web.Mvc.SelectListItem>();
As none of the existing answers made this clear to me, I post this. Perhaps it helps anybody.
your code is correct because in some cases it does not work, I also do not know where the error comes from but this can help you solve the problem, move the code in the head of the view like this:
index.cshtml:
#using expert.Models;
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
Manager db = new Manager();
ViewBag.FORM_PRESTATION = new SelectList(db.T_BDE_PRESTATION_PRES.OrderBy(p => p.PRES_INTITULE).Where(p => p.T_B_PRES_ID == null), "PRES_ID", "PRES_INTITULE");
}
<div class="form-group">
<label class = "w3-blue" style ="text-shadow:1px 1px 0 #444">Domaine:</label>
<div class="col-md-10">
#Html.DropDownList("FORM_PRESTATION", null, htmlAttributes: new { #class = "w3-select ", #required = "true" })
</div>
</div>
you can use this:
var list = new SelectList(countryList, "Id", "Name");
ViewBag.countries=list;
#Html.DropDownList("countries",ViewBag.countries as SelectList)
Replace "country" with "countrydrop" in your view like this...
#Html.DropDownList("countrydrop", (IEnumerable<SelectListItem>)ViewBag.countrydrop,"Select country")
Could be like for ASP.NET MVC Framework
#Html.DropDownList("country", ViewBag.countrydrop as List<SelectListItem>,"Select country")
or ASP.NET Core MVC
<select class="class" id="country"
asp-items="#(new SelectLits(ViewBag.countrydrop,"Value","Text"))">
You are facing this problem because when you are posting your forms so after reloading your dropdown is unable to find data in viewbag. So make sure that code you are using in get method while retrieving your data from db or from static list, copy paste that code into post verb as well..
Happy Coding :)

ASP.NET MVC using more than 1 DataContext Insert Method

So i recently want to try using more than 1 database
my main problem is the attribute on 1st and 2nd entities is different, so for example in 1st entities sample_table1 contain: "member_id" and "member_code" and the 2nd entities sample_table_2 contain "student_id" and "student_code" it's just the naming, the value of the attribute is same, so member_id = student_id, member_code = student_code
Example:
Controller
private MyEntities db = new MyEntities ();
//not sure know by add this one, my controller can connect 2 database, but the intellisense is working when i'm using db2 class
private MyEntities2 db2 = new MyEntities2 ();
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateSomething(sample_table1 sample_table1, sample_table2 sample_table2)
{
if (ModelState.IsValid)
{
//insert data to 1st Entities
db.sample_table1.Add(sample_table1);
db.SaveChanges();
//insert data to 2nd Entities
"???" // because the attribute name on 2nd entities is not the same as the 1st entities, i cannot using either sample_table1 & sample_table2
db2.SaveChanges();
}
}
Views
#model 1st_entites_data_model.Models.sample_table1
// i don't know for sure but the 2nd entities data model won't appear when i add view
#{
ViewBag.Title = "Create Something";
}
#using (Html.BeginForm("CreateSomething", "test", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
//i'm using only the 1st entities, because there is no need for user input the same data value twice
#Html.TextBoxFor(model => model.sample_table1.member_id)
#Html.ValidationMessageFor(model => model.sample_table1.member_id)
#Html.TextBoxFor(model => model.sample_table1.member_code)
#Html.ValidationMessageFor(model => model.sample_table1.member_code)
}
i cannot change the 2nd entities name because somebody else is making the 2nd entities, and i cannot edit the database structure...
Thank You Very Much...
You can use automapper to transfer data from first to second entity.After that your code will be:
...
db.sample_table1.Add(sample_table1);
db.SaveChanges();
//insert data to 2nd Entities
var sample_table2 = Mapper.Map<sample_table2>(sample_table1);
db2.sample_table_2.Add(sample_table2);
db2.SaveChanges();
...

Can I use IEnumerable<> inside a View?

In _Layout.cshtml
#model DynaPortalMVC.Models.Page
#using System.Linq
<ul>
#IEnumerable<model.Page> pages = model.Where(x=>x.CompanyID == 1);
#foreach (var item in pages)
{
<li>item.Title</li>
}
</ul>
In view iam trying to filter the model object called 'page' and get a list of pages whose id is 1. I need to iterate through this to show the menu.
Code inside Controller
public ActionResult Menu(string PageName)
{
//
return View(PageName, db.Pages);
}
Please tell me, how to filter out this model object to a list? I get errors on using IEnumerable.
Solved
I changed the model object to IEnumerable in view page.
#model IEnumerable<DynaPortalMVC.Models.Page>
You can skip assigning the result of your query into an IEnumerable variable unless you will use it somewhere else on the page. So you can just do this:
#model DynaPortalMVC.Models.Page
#using System.Linq
<ul>
#foreach (var item in model.Where(x=>x.CompanyID == 1))
{
<li>#item.Title</li>
}
</ul>
You need
# {IEnumerable<model.Page> pages = Model.Where(x=>x.CompanyID == 1);}
#model IEnumerable<DynaPortalMVC.Models.Page>
#{
ViewBag.Title = "Page";
}

Passing data from Html.Action to the partial view

I'm still relatively new to MVC 3. I need to pass data from my #Html.Action methods through the controller to a partial view.
So here is my flow.
I'll call #Html.Action like this:
#Html.Action("SidebarMain", "Home", new List<int>(new int[] {1, 2, 3}))
Then it will hit my Controller. Here is my method in my Home Controller:
public ActionResult SidebarMain(List<int> items)
{
return View(items);
}
Then my Partial View should be able to access the data like so:
#model List<int>
#{
ViewBag.Title = "SidebarMain";
Layout = null;
}
<div>
#foreach (int item in Model)
{
<div>#item</div>
}
</div>
BUT: I'm getting a null exception for the Model, meaning It's not passing through.
Try this:
Html.Action("SidebarMain", "Home", new { items = new List<int>(new int[] {1, 2, 3}) })
And put a breakpoint in your SidebarMain Action to see, if you are getting items
In short: your code is missing the items parameter name in the Html.Action().
Other than that the code should be functional.
Html.Action("SidebarMain", "Home", new {items = new List<int>(new int[] {1, 2, 3}) })
As a suggested practice, i would use a dedicated ViewModel in my view rather than just sending the array of integers. Because, in this way of a clean ViewModel - a container of your properties that you display in the view, your code may add other properties later on, as our code always evolves.
Reference to the usage of a ViewModel concept: Exercise 5: Creating a View Model
Good answer from DarthVader. Are you returning this as Ajax? If you are embedding it in a main view, you should really return it as a PartialView with
return PartialView("SidebarMain", model);
This is where SidebarMain is the name of the partial view that you are returning. Try this in combination with what DarthVader suggested and make sure that you're getting a model to pass back to the view.
After posting, I realized that you are using Html.Action. If this is a true sidebar, it SHOULD be loaded with ajax as a partial view and you should be calling
Ajax.ActionLink("SidebarMain", "Home", new { items = new List<int>(new int[] {1, 2, 3}) })
This will allow you stay on your current page. If you aren't looking for ajax functionality, I apologize for the rabbit trail :)
DarthVader's suggestion may have worked. This is what I ended up doing:
1) Removed the controller
2) Called it like this:
#{Html.RenderPartial("SidebarMain", new int[] {1,3,4,2});}
3) Here is my view code:
#model int[]
#foreach( int item in Model){
...

Categories

Resources