Creating a dropdown list in MVC nhibernate - asp.net-mvc

I'm creating an application in hibernate where i need to create a dropdown list in my Create View.
The dropdownlist items are fetched through a function called getHobbytype() and from that I need to store the selected value into a different database.
I have written this in my controller:
ViewData["Hobby_type"] =
new SelectList(new Hobby_MasterService().GetHobbyType(),"Hobby_Types");
And this in my Create View:
#Html.DropDownListFor(Model =>
Model.Hobby_Types,(IEnumerable<SelectListItem>)ViewData["Hobby_type"])
Through this I'm able to create the dropdown list but it is giving me this error inside my view on the dropdown:
There is no ViewData item of type 'IEnumerable' that has the key 'Hobby_Types'.
Here is my GetHobbyType Method:
public IList<String> GetHobbyType()
{
log.Debug("Started");
ISession session = DataAccessLayerHelper.OpenReaderSession();
IList<String> htype = null;
ITransaction transaction = null;
try
{
transaction = session.BeginTransaction();
htype = session.CreateSQLQuery("SELECT Hobby_Types FROM Hobby_Type").List<String> ();
session.Flush();
transaction.Commit();
}
catch (Exception ex)
{
if (transaction != null && transaction.IsActive)
transaction.Rollback();
log.Error(ex);
}
log.Debug("End");
return htype;
}
Please tell me where I'm going wrong.

Is this a typo:-
#Html.DropDownListFor(Model =>
Model.Hobby_Types,(IEnumerable<SelectListItem>)ViewData["Type"])
Should it not be
#Html.DropDownListFor(Model =>
Model.Hobby_Types,(IEnumerable<SelectListItem>)ViewData["Hobby_type"])
Also your error says 'IEnumerable' that has the key 'Hobby_Types'.
The key in ViewData is case sensitive (not to mention the error has an S on the end)
I would also reccomend using a ViewModel rather than ViewData. See this Google search
edit The GetHobbyType Method returns a List so try this:-
ViewData["Hobby_type"] =
new SelectList(
new Hobby_MasterService().GetHobbyType()
.Select(x => new SelectListItem { Text = x, Value = x }).ToList()
,"Hobby_Types");
I also suggest looking at using a viewmodel as it will save you lots of headaches!

You can try this all.
You have to write a service named GetAllStudents()
public IList<Student> GetAllStudents()
{
log.Debug("Started");
ISession session = DataAccessLayerHelper.OpenReaderSession();
IList<Student> students = null;
ITransaction transaction = null;
try
{
transaction = session.BeginTransaction();
ICriteria criteria = session.CreateCriteria(typeof(Student));
students = criteria.List<Student>();
session.Flush();
transaction.Commit();
}
catch (Exception ex)
{
if (transaction != null && transaction.IsActive)
transaction.Rollback();
log.Error(ex);
}
finally
{
if (transaction != null)
transaction.Dispose();
if (session != null && session.IsConnected)
session.Close();
}
log.Debug("End");
return students;
}
In controller:
ViewBag.std = new StudentService().GetAllStudents(); // ViewBag.std will hold all students.
In create View:
#Html.DropDownListFor(model => model.Name, new SelectList(ViewBag.std, "Id", "Name"), "-- Select --")
First parameter is responsible for Linq expression for class property which you want to place in dropdown.
Second one is IEnumerable item list.
Third data value field.(Primary key)
Last one is Data text field which you want to display in drop down list.

Related

Updating collection property in explicit model binding VS implicit model binding?

I have an entity model that has a collection property (many-to-many relationship) of Users signed up for the application.
in the Edit view I used implicit model binding to edit task object with the single properties (Title, DueDate, etc..) and Users (checkboxes) :
public ActionResult Edit([Bind(Include = "Id,Title,Description,DueDate,Status")] UserTask task, string[] asndUsers/*users IDs*/)
{
if (ModelState.IsValid)
{
task.Users = new List<ApplicationUser>();
if (asndUsers != null)
{
foreach (var userId in asndUsers)
{
var user = context.Users.Find(userId);
task.Users.Add(user);
}
}
context.Entry(task).State = EntityState.Modified;
context.SaveChanges();
return RedirectToAction("Index");
}
return View(task);
}
but this didn't work, the single properties was updated but the Users couldn't be updated.
I then used the explicit model binding
var task = context.Tasks.Include(t => t.Users).SingleOrDefault(s => s.Id == id);
task.Users = new List<ApplicationUser>();
foreach (var userId in asndUsers)
{
var user = context.Users.Single(u => u.Id == userId);
task.Users.Add(user);
}
if (TryUpdateModel(task, "", new string[] { "Title", "Description", "DueDate", "Status" }))
{
context.SaveChanges();
return RedirectToAction("Index");
}
it works, but have no idea what it did that implicit binding didn't

MVC Dropdownlist giving Object reference not set to an instance of an object error [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I came across all other similar question on SO but I couldn't understand how to implement the solutions to my case, or which solution. This is my 2nd day in MVC and I'm stuck with something probably very simple.
What I'm trying to do is, checking a condition and returning to register page with a warning if the condition is met. When it happens, dropdownlist gives the titular error.
Checking for conditions before triggering SP. Problematic one is CompanyExists.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterViewModel model, FormCollection coll)
{
bool UserExists = CompanyDB.User_Check_Exists(model.Email);
bool CompanyExists = CompanyDB.Company_Check_Exists(model.CountryCode, model.TaxIdNo);
if (!ModelState.IsValid)
{
return View(model);
}
if (CompanyExists)
{
ViewBag.CompanyExists = CompanyExists;
return View(model);
}
if (coll["chkContract"] != "on")
{
ViewBag.ContractError = true;
return View(model);
}
ViewBag.UserExists = UserExists;
if (UserExists)
{
string UserEmail = model.Email;
ViewBag.UserEmail = model.Email;
}
string error = String.Empty;
RegistrationDB.Registration_Add(model, out error);
return View("RegisterComplete");
}
Dropdown population:
public class MVCUtility
{
public static ClaimsIdentity CurrentClaimsIdentity{
get { return null; }
}
public static List<SelectListItem> DataTableToListItem(DataTable Table, string ValueField, string TextField) {
List<SelectListItem> items = new List<SelectListItem>();
foreach (DataRow dr in Table.Rows) {
SelectListItem item = new SelectListItem() { Value = dr[ValueField].ToString(), Text = dr[TextField].ToString() };
items.Add(item);
}
return items;
//SelectList list = new SelectList(items);
//return list;
}
}
and the dropdown line at register.cshtml
#Html.Bootstrap().DropDownListFor(t => t.CountryCode, MVCUtility.DataTableToListItem((DataTable)ViewBag.CountryList, "Code", "Name")).HtmlAttributes(new { #style = "width:100%;" })
What I understood from other questions was, I need to repopulate the dropdown list by sending data to it before the return(View); line. I don't know how I can manage it with these parameters.
ViewBag.CountryList is null.
In Controller
Without Selected Value
ViewBag.CountryList = new MultiSelectList("Bind Your Country List", "Code", "Name");
With Selected Value
ViewBag.CountryList = new MultiSelectList("Bind Your Country List", "Code", "Name","Selected Code");
In cshtml Page
#Html.DropDownList("CountryCode", (MultiSelectList)ViewBag.CountryList, new { id = "CountryCode" })

Updating database entry MVC Entity Framework

I have a Payment model with a 'Status' boolean value which defaults to false. Once payment has been made, I need to update that specific payment's 'Status' to true.
Here's the code I've been trying to use to change the specific database entry, but it's just not changing it. What am I doing wrong?
Payment payment = new Payment();
payment = db.Payments.Find(orderId);
db.Entry(payment).State = EntityState.Modified;
payment.Status = true;
db.SaveChanges();
Thanks!
This is what ended up working:
using (var con = new ApplicationDbContext())
{
payment = con.Payments.First(x => x.Id == orderId);
payment.Status = true;
con.Payments.Attach(payment);
var entry = con.Entry(payment);
entry.Property(e => e.Status).IsModified = true;
con.SaveChanges();
}
Payment payment = new Payment();
payment = db.Payments.Find(orderId);
payment.Status = true;
db.Entry(payment).State = EntityState.Modified;
db.SaveChanges();
The reason all of these are failing is because either the Payment object is never attached to the DBContext or the orderId doesn't actually match up with the PK on the Payments table. In order for SaveChanges() to actually work, the object you're changing needs to be tracked by the DBContext, not just have its EntityState set to Modified. Also all these examples seem grossly overcomplicated.
using (var db = new DbContext())
{
// make sure you have the right column/variable used here
var payment = db.Payments.FirstOrDefault(x => x.Id == orderId);
if(payment == null) throw new Exception("Invalid id: " + orderId);
// this variable is tracked by the db context
payment.Status = true;
db.SaveChanges();
}
If you just have your entity id, just do like Ali Golshani said. But if you already have the entity and just want to update, you can do this way:
public void Update(Payment payment, int orderId)
{
//first find the entity to update
Payment oldEntity = DbSet.Find(orderId);
//detach this entity from the DbSet
Db.Entry(oldEntity).State = EntityState.Detached;
//set the state from the entity that you just received to modified
Db.Entry(obj).State = EntityState.Modified;
}
Detaching avoids the error message: "Attaching an entity failed because another entity of the same type already has the same primary key value".
I hope that it helps.
Try this one:
Payment payment;
using (var context = new DBContext()) //replace the name of your context
{
payment = context.Payments.Find(orderId);
}
if(payment != null)
{
payment.Status = true;
}
using (var context = new DBContext()) //replace the name of your context
{
context.Payments.Attach(payment);
context.Entry(payment).State = System.Data.EntityState.Modified;
context.SaveChanges();
}
As mentioned here:
The Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database.
So be sure that Payment class looks like this:
public class Payment
{
[Key]
public int Id {get; set;}
public bool Status {get; set;}
}
And your Entry save logic could look like this:
Payment payment = null;
using (var ts = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))
{
using (var context = new DBContext())
{
context.Database.Log = s => { System.Diagnostics.Debug.WriteLine(s); };
payment = context.Payments.Find(orderId);
if(payment != null)
{
payment.Status = true;
context.Entry(payment).State = System.Data.EntityState.Modified;
}
else
{
context.Payments.Add(new Payment(){
Status = true
});
}
context.SaveChanges();
}
ts.Complete();
}
Added transaction scope to be sure that it is properly open and close, and added sql query logging to debug window.

accessing viewbag in the view

net MVC. I have assigned a list of objects to the viewbag property can anyone please tell me as to how i can get the list in the view to use it in the drop down list? here is my controller code & view code
Controller:
public ActionResult GetSection(int sectionId,int contactId)
{
ContactDetailSectionModel contactDetailSection = new ContactDetailSectionModel { SectionId = sectionId,ContactId=contactId };
contactDetailSection.FetchAllSubsections();
ContactDetailSectionModel customSections = new ContactDetailSectionModel();
customSections.FetchCustomSubSections();
if(customSections != null && customSections.ContactDetailSubSections != null)
{
ViewBag.CustomSubSections = customSections.ContactDetailSubSections;
}
return PartialView("~/Views/Contacts/Details/EditSection.cshtml", contactDetailSection);
}
View Code:
#Html.DropDownListFor(m => m.ContactDetailSubSections[1], new SelectList(ViewBag.CustomSubSections , "Name", "Name",Model.ContactDetailSubSections[1].Name))
#Html.TextAreaFor(m => m.ContactDetailSubSections[1].Text)
I think the first parameter in your #Html.DropDownlist should be string or some scalar quantity it cannot be a collection.

MVC 4 Session Variable getting updated and I don't know how

I have a method to retrieve session variables, in this case Organizations. For some reason, when I call the get session method the get Organizations and pass the data to a SelectList method to handle some naming logic, the session variable is getting updated. I don't wanted the session values updated and don't understanding what is happening. Below are all the methods. What am I missing?
Controller Method:
public ActionResult Create()
{
SignUpEventFormModel model = new SignUpEventFormModel();
SelectListHelpers listHelper = new SelectListHelpers();
model.OrganizationList = listHelper.GetOrgSelectList(sessionRepository.GetUserSession().Organizations, null);
return View(model);
}
Get User Session Method:
public UserSession GetUserSession()
{
UserSession us = (UserSession)HttpContext.Current.Session["UserSession"];
if (us == null)
{
string email = HttpContext.Current.User.Identity.Name;
SessionSetupRepository sessionsetupRepository = new SessionSetupRepository(new UserRepository(null, null), new SignUpRepository(), new ActivityRepository(), new OrganizationRepository());
us = sessionsetupRepository.SetupUserSession(email);
}
return us;
}
Get Org Select List Method:
public SelectList GetOrgSelectList(IEnumerable<Organization> Orgs, int? SelectedOrgID)
{
List<Organization> OrgList = Orgs.ToList();
OrgList.Where(o => !o.IsAdmin).ToList().ForEach(o => o.Name = o.Name + " (Permission Request Required)");
if (SelectedOrgID.HasValue)
return new SelectList(OrgList, "OrganizationID", "Name", (int)SelectedOrgID);
else
return new SelectList(OrgList, "OrganizationID", "Name");
}
Created a IList parameter and converted the organizations to a list.

Resources