how to pass a where statement in a viewbag - asp.net-mvc

I am trying to pass a where statement in a viewbag to a view. I am trying to pass the equipment status that equals 'In' but it won't work. It wont display the condition.
ViewBag.EquipmentID = new SelectList(db.Equipments.Where(o => o .EquipmentStatus== "In"), "EquipmentID", "EquipmentType", hire.EquipmentID);
my view to select an equipment is:
<div class="form-group">
#Html.LabelFor(model => model.EquipmentID, "EquipmentID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("EquipmentID", String.Empty)
#Html.ValidationMessageFor(model => model.EquipmentID)
</div>
</div>
My hire model is:
public class Hire
{
public int HireID { get; set; }
public int EquipmentID { get; set; }
public int PurchaseID { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReturnedDate { get; set; }
public virtual Purchase Purchases { get; set; }
public virtual Equipment Equipments { get; set; }
}
using the viewmodel method it says in the view that "the name 'model' does not exist in the current context"
this is my view:
<div class="form-group">
#Html.LabelFor(model => model.EquipmentID, "EquipmentID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.EquipmentID, model.SelectList)
#Html.ValidationMessageFor(model => model.EquipmentID)
</div>
</div>
The 'model' in 'model.Equipment' is underlined with the error
this is my controller:
public ActionResult Create(int ID)
{
var hire = new Hire();
Purchase purchase = db.Purchasess.Find(ID);
ViewHire responseModel = new ViewHire()
{
PurchaseID = purchase.PurchaseID,
EquipmentID = hire.EquipmentID,
SelectList = new SelectList(db.Equipments.Where(o => o.EquipmentStatus == "In"), "EquipmentID", "EquipmentType", hire.EquipmentID),
};
ViewBag.PurchaseID = new SelectList(db.Purchasess, "PurchaseID", "PurchaseID");
return View(responseModel );
}

Consider this:
ViewBag.Equipments = new SelectList(db.Equipments.Where(o => o .EquipmentStatus== "In"), "EquipmentID", "EquipmentType");
And in your view write:
#Html.DropDownListFor(model=>model.EquipmentID,(SelectList)ViewBag.Equipments,String.Empty)

I think that the issue is that you are passing your model through the ViewBag and not passing it through to your view using View() in your controller.
Therefore, when you use a Html helper like #Html.DropDownList(model => model.Property) it won't find the values that you're wanting to pass through.
Your view should have a view model defined in there at the top of the file, then your view knows what type of view model to expect, such as:
#model MyViewModel
Your view model should be defined as a class within your project, such as:
public class MyViewModel
{
public int EquipmentId { get; set; }
public SelectList SelectList { get; set; }
}
Then within your controller, assign the values to an instance of your class:
public ActionResult Index(int id)
{
// Code to retrieve hire and db instances...
var responseModel = new MyViewModel()
{
EquipmentId = hire.EquipmentID,
SelectList = new SelectList(db.Equipments.Where(o => o .EquipmentStatus== "In"), "EquipmentID", "EquipmentType", hire.EquipmentID),
};
// Return your view model to the view without using the ViewBag
return View(responseModel);
}
Now that you're passing your model through, your HTML helpers will have access to the values:
#model MyViewModel
#Html.DropDownListFor(model => model.EquipmentId, model.SelectList)

Related

MVC Razor two level Model for ListBoxFor

Is there a way in the view to drill down one level to get the data object in the GenericValues? I know that I can change the model around to make it work but I didnt want to add extra model classes?
View
<div class="form-group row">
#Html.LabelFor(model => model.selectedLanguage)
#Html.ListBoxFor(
x => x.selectedLanguage,
new SelectList(Model.ListOfLanguages, "Value.Value", "Value.Name"),
new { id = "multiselectLanguage", #class = "form-control" })
</div>
Model
public List<LanguageModel> ListOfLanguages { get; set; }
public class LanguageModel
{
public string ISOCode { get; set; }
public GenericValues Values { get; set; }
}
public class GenericValues
{
public string Name { get; set; }
public int Value { get; set; }
}
You can use linq to get list<GenericValues>:
#Html.ListBoxFor(
x => x.selectedLanguage,
new SelectList(Model.ListOfLanguages.Select(x => x.Values).Distinct(), "Value", "Name"),
new { id = "multiselectLanguage", #class = "form-control" })

Problem in showing ViewModel in Create form

I am learning how to use ViewModel to show the fields from 2 different models. I have one model containing the MsgTypeId, MsgType and MsgStatus and the another model OptStatus containing the StatusId, StatusName and StatusValue. The MsgStatus will be shown in form of drop down list and show all the values in OptStatus. Both models have a separate database table to store their values.
namespace theManager.Areas.Settings.Models
{
public class OptStatus
{
[Required]
[Key]
public int StatusId { get; set; }
[Required]
public string StatusName { get; set; }
[Required]
public char StatusValue { get; set; }
}
}
namespace theManager.Areas.Settings.Models
{
public class OptMsgType
{
[Required]
[Key]
public int MsgTypeId { get; set; }
[Required]
public string MsgType { get; set; }
[Required]
public string MsgStatus { get; set; }
}
}
I have created a ViewModel to show these fields in the Create form of OptMsgType. However, when I run the code, I got an error
"System.NullReferenceException: 'Object reference not set to an instance of an object.'"
I would like to ask if there is something wrong with my ViewModel. Thanks!
namespace theManager.Areas.Settings.ViewModels
{
public class OptMsgTypeCreateViewModel
{
public OptMsgType OptMsgType { get; set; }
public IEnumerable<SelectListItem> OptStatuses { get; set; }
}
}
OptMsgTypeController.cs
public IActionResult Create(int id)
{
var OptMsgTypeViewModel = new OptMsgTypeCreateViewModel();
OptMsgTypeViewModel.OptStatuses = _context.OptStatus.ToList().Select(x => new SelectListItem
{
Text = x.StatusName,
Value = x.StatusValue.ToString()
});
OptMsgTypeViewModel.OptMsgType = _context.OptMsgType.Where(a => a.MsgTypeId == id).FirstOrDefault();
//var v = _context.OptMsgType.Where(a => a.MsgTypeId == id).FirstOrDefault();
return View(OptMsgTypeViewModel);
}
I have problems in displaying the Create form which will show the fields declared in the ViewModel.
#model theManager.Areas.Settings.ViewModels.OptMsgTypeCreateViewModel
#{
ViewData["Title"] = "Create";
Layout = null;
}
<h2>Message Type Settings</h2>
#using (Html.BeginForm("Create","OptMsgType", FormMethod.Post, new { id= "popupForm" }))
{
if (Model != null && Model.OptMsgType.MsgTypeId > 0)
{
#Html.HiddenFor(a=>a.OptMsgType.MsgTypeId)
}
<div class="form-group">
<label>Message Type ID</label>
#Html.TextBoxFor(a=>a.OptMsgType.MsgTypeId,new { #class = "form-control" })
#Html.ValidationMessageFor(a=>a.OptMsgType.MsgTypeId)
</div>
<div class="form-group">
<label>Leave Type</label>
#Html.TextBoxFor(a => a.OptMsgType.MsgType, new { #class = "form-control" })
#Html.ValidationMessageFor(a => a.OptMsgType.MsgType)
</div>
<div class="form-group">
<label>Status</label>
#Html.DropDownListFor(model => model.OptStatuses, new SelectList(Model.OptStatuses, "Value", "Text"), htmlAttributes: new { #class = "form-control", id = "OptStatus" })
#Html.ValidationMessageFor(a => a.OptStatuses)
</div>
<div>
<input type="submit" value="Create" />
</div>
}
The System.NullReferenceException indicates that you are using a field without initializing it. It coulbe a problem with your view model or it could be a problem anywere else. For example from the code smaple is not possible to see where you initialize the context you are using to get the data, and that could be the cause of the exception you are getting.
Either way I would advise you to pay attention to yout IDE, it usualy indicates in which line adnd class the exception is being thown. If you navigate to that class at that line you will easily identify which field can be de cause of the exception.
Regarding your view model, its considered a good practice to always initialize the lists on your model on the constructor of your class. This way you can guarantee that they are already initialized when you try to use them.
So my sugestion would be to initialize your list on the constructor of your viewmodel
public OptMsgTypeCreateViewModel()
{
OptStatuses = new List<OptStatus>();
}
#George, thanks for the reply. Please try this then: instantiate your class in the viewmodel.
public class OptMsgTypeCreateViewModel
{
public OptMsgTypeCreateViewModel()
{
OptMsgType = new OptMsgType();
}
public OptMsgType OptMsgType { get; set; }
public IEnumerable<SelectListItem> OptStatuses { get; set; }
}
hi in action controller you should change this code:
OptMsgTypeViewModel.OptStatuses = _context.OptStatus.ToList().Select(x => new SelectListItem
{
Text = x.StatusName,
Value = x.StatusValue.ToString()
});
I think _context.OptStatus.ToList() in null so you get this exception. change code to this:
OptMsgTypeViewModel.OptStatuses =new list<SelectListItem>();
var temp= _context.OptStatus.ToList();
if(temp!=null&&temp.count()>0)
{
OptMsgTypeViewModel.OptStatuses = temp.Select(x => new SelectListItem
{
Text = x.StatusName,
Value = x.StatusValue.ToString()
}).tolist();
}
EDIT:
I think this object "Model.OptMsgType" is null
change code in view like this:
if (Model != null && Model.OptMsgType!=null && Model.OptMsgType.MsgTypeId > 0)
{
#Html.HiddenFor(a=>a.OptMsgType.MsgTypeId)
}

Populate DropDownListFor: HtmlHelper does not contain a definition for 'DropDownListFor'

I have an ever-changing list of Industries that I'd like a user to select from when creating a new Survey.
I could accomplish this with either a ViewModel or ViewBag (I think). I'm attempting to do it with ViewBag. Getting the DropDownListFor error:
CS1928 HtmlHelper<Survey> does not contain a definition for DropDownListFor and the best extension method overload SelectExtensions.DropDownListFor<TModel, TProperty>(HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>, IEnumerable<SelectListItem>, object) has some invalid arguments 2_Views_Surveys_Create.cshtml
Survey model, with foreign key to Industry:
public class Survey
{
[Key]
public int id { get; set; }
[Display(Name = "Survey Name")]
public string name { get; set; }
[Display(Name = "Industry")]
public int industryId { get; set; }
[ForeignKey("industryId")]
public virtual Industry industry { get; set; }
}
Controller to load Industries SelectList into ViewBag:
// GET: Surveys/Create
public ActionResult Create()
{
ViewBag.Industries = new SelectList(db.industry, "Id", "Name");
return View();
}
Create view:
<div class="form-group">
#Html.LabelFor(model => model.industryId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.industryId, ViewBag.Industries, "-Select Industry-")
#Html.ValidationMessageFor(model => model.industryId, "", new { #class = "text-danger" })
</div>
</div>
Properties of the ViewBag have no type that the compiler can use to decide which overload of the method to call. Help the compiler by using an explicit cast.
#Html.DropDownListFor(model => model.industryId, (IEnumerable<SelectListItem>)ViewBag.Industries, "-Select Industry-")

MVC Partial View throwing error on dropdownfor

I have a partial view I want to display as a search interface. Every time it tells me I get the error
There is no ViewData item of type IEnumerable that has the key resource_type_id.
I have tried so many things to make this work but nothing helps.
This is my view calls the partialview
#model IEnumerable<NewSAMACentral2._0.ViewModel.MemberResourcesViewModel.MemberResource>
#{
ViewBag.Title = "Add Resource To Folder";
}
<h2>Add Resource To Folder</h2>
<div>
#{Html.Partial("SearchResource", new NewSAMACentral2._0.ViewModel.MemberResourcesViewModel.ResourceSearch());}
</div>
#using (Ajax.BeginForm("InsertAttendee", "Meetings", new AjaxOptions { HttpMethod = "POST" }))
{
if (Model.Any())
{
}
}
This is my partialview
#model NewSAMACentral2._0.ViewModel.MemberResourcesViewModel.ResourceSearch
#using (Ajax.BeginForm("AddAttendee", "Meetings", new AjaxOptions { UpdateTargetId = "AddAttendee", HttpMethod = "POST" }))
{
<div class="form-group">
<label for="keyword">Keyword(s): </label>#Html.TextBox("keyword", null, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(model => Model.resource_type_id)
#Html.DropDownListFor(model => Model.resource_type_id, Model.resource_type, "-- Select --", new { #class = "form-control" })
</div>
<div class="form-group">
<label for="author">Author(s): </label>#Html.TextBox("author", null, new { #class = "form-control" })
</div>
<div class="form-group">
<input type="submit" name="submit" value="Search" />
</div>
}
This is the controller that never seems to get called...
public PartialViewResult SearchResource()
{
var results = new MemberResourcesViewModel.ResourceSearch();
results.resource_type = db.Resource_Types.Select(s => new SelectListItem
{
Text = s.name,
Value = s.id.ToString()
}).Distinct().OrderBy(x => x.Text);
return PartialView(results);
}
This is the ViewModel
namespace NewSAMACentral2._0.ViewModel
{
public class MemberResourcesViewModel
{
public IEnumerable<MemberResource> MemberResourceResult;
public MemberResource memberResource;
public class MemberResource
{
public ResourceSearch resource_search { get; set; }
[Key]
public int Id { get; set; }
[DisplayName("Resource Title")]
public string title { get; set; }
public IEnumerable<SelectListItem> resource_type { get; set; }
[DisplayName("Resource Type")]
public string resource_type_id { get; set; }
[DisplayName("Keyword")]
public string keyword { get; set; }
[DisplayName("Author")]
public string author { get; set; }
[DisplayName("Subject Type")]
public string subject_type { get; set; }
[DisplayName("Industry")]
public string industry { get; set; }
[DisplayName("Description")]
public string description { get; set; }
}
public class ResourceSearch
{
[DisplayName("Author")]
public string author { get; set; }
public IEnumerable<SelectListItem> resource_type { get; set; }
[DisplayName("Resource Type")]
public string resource_type_id { get; set; }
[DisplayName("Keyword")]
public string keyword { get; set; }
}
}
}
You have to be carefull with capital letters and put model not Model:
#Html.LabelFor(model => model.resource_type_id)
#Html.DropDownListFor(model => model.resource_type_id, model.resource_type, "-- Select --", new { #class = "form-control" })
On your main View Action (not partial view action result):
var types = db.Resource_Types.Distinct().OrderBy(x => x.Text).ToList();
SelectList typeList = new SelectList(types, "ID", "Name");
ViewBag.Types = typelist;
All that was done there was pull your objects from the DataBase. Then we turned that into a Select list with 'ID' as the value field and 'Name' as the text field. Then we put that select list in a viewbag to be used by our view.
Next In your partial view:
#Html.DropDownListFor(model => model.resource_type_id, new SelectList(ViewBag.Types, "value", "text"), "-- Select --", new { #class = "form-control" })
The only difference in this HTML is its pulling values from the select list so you never have to worry about it even hitting the partial view controller. I also changed the capital 'M' in model to a lowercase because not needed
Remember to put the code for the ViewBag in your main actionresult, not the partial view action result.
As Stephen commented below all you really need is :
#Html.DropDownListFor(model => model.resource_type_id, (SelectList)ViewBag.Types, "-Select-", ...)
Your error occurs because the value of Model.resource_type is null when used inside the DropDownListFor() method.
In your main view you use Html.Partial() to render a partial view named SearchResource.cshtml, passing it a new instance of your class ResourceSearch. But ResourceSearch does not have a default constructor which initializes the resource_type property so its null, hence the exception.
Your naming conventions and use of nested models make it difficult to understand, and you have not shown the GET method for the main view, but I suspect you are wanting to actually call the SearchResource() method on your controller which will return the partial view of the form. In which case you need to use
#{Html.RenderAction("SearchResource")}
which will call the method and return its partial. Since that method initializes a new instance of ResourceSearch and populates its resource_type property, it will no longer be null
Note you should also consider applying the [ChildActionOnly] attribute to the method so it cant be called by the user entering the url in the address bar.

EditUserViewModel needs a DropDownListFor()

Right now I have added a Region to the ApplicationUser model in Identity 2.0
On the UsersAdmin view, Edit action, I have the following stock code to display/edit the Region of the User:
<div class="form-group">
#Html.LabelFor(model => model.Region, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Region, new { #class = "form-control" })
</div>
</div>
How do I make that TextBox into a DropDownList that allows the user to choose from a list of Region names where Regions is part of ApplicationDbContext?
public class Region
{
[Key]
public Guid ID { get; set; }
public string Name { get; set; }
public Company Company { get; set; }
public Region()
{
this.ID = Guid.NewGuid();
}
}
You could use a view model. In order to render a dropdown you need 2 properties in your view model: a scalar property to hold the selected value and a collection property to represent the list of possible values to be displayed:
public class MyViewModel
{
public Guid SelectedRegionID { get; set; }
public IEnumerable<SelectListItem> Regions { get; set; }
}
That your controller action will populate and pass to the view:
public ActionResult Index()
{
var viewModel = new MyViewModel();
viewModel.Regions = db.Regions.ToList().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Name,
});
return View(viewModel);
}
and in the corresponding strongly typed view you could use the DropDownListFor helper:
#model MyViewModel
<div class="form-group">
#Html.LabelFor(model => model.Region, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedRegionID, Model.Regions, new { #class = "form-control" })
</div>
</div>

Resources