Multiple models in same view in asp.net mvc 4 - asp.net

I'm using asp.net mvc 4 & Entity Framework 6 to make a website where after user login, the table records will show & the ID of the user will show as Session. But when I run, after login, I get this error, Object reference not set to an instance of an object. I've made a custom model where two DbSet from seperate EF6 models are attached. My code is below,
Custom Model
public class MkistatVsUserLogin
{
public sample_1 sample_1 { get; set; } //Login Model
public IEnumerable<mkistat> mkistats { get; set; } //Table Model
}
Controller
[HttpPost]
public ActionResult Login(sample_1 id)
{
if (ModelState.IsValid)
{
var uservar = db.sample_1.Where(a => a.boid.Equals(id.boid)).FirstOrDefault();
if (uservar != null)
{
Session["UserBOID"] = uservar.boid.ToString();
return RedirectToAction("UserLogin");
}
}
var mkimodel = new MkistatVsUserLogin { mkistats = dsedb.mkistats.ToList() };
return View(id);
return View(mkimodel);
}
View
#model ABCoLtd.Models.MkistatVsUserLogin
#if (Session["UserBOID"] != null)
{
<li>Welcome, <b>#Session["UserBOID"].ToString()</b></li>
}
<a class="btn btn-default" href="#Url.Action("UserLogout", "Home")">Log Out</a>
#foreach (var item in Model.mkistats)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.MKISTAT_ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.MKISTAT_PHONE_NO)
</td>
</tr>
}
Is there something wrong with my code? If it is then please give me a solution. All I want is to use both models at the same view where user login model will be used in Session & table model to list all the records.

Remove bellow line
return View(id);
and in your return View line also mention View or ActionMethod name
return View("ViewName",mkimodel)
In your action method, Use Session to pass ID
Session["UserID"] = id;
You can use the same in your View as :
<html>
-----Your CODE
<body>
------Your CODE
#Session["UserID"]
------Your CODE
</body>
</html>

You can create a ViewModel to handle :
namespace ABCoLtd.ViewModels
{
public class LoginVM
{
public MkistatVsUserLogin MkistatVsUserLogin {get;set;}
public int Id {get;set;}
}
}
and in action pass this way:
var mkimodel = new MkistatVsUserLogin { mkistats = dsedb.mkistats.ToList() };
LoginVM vm = new LoginVM();
vm.MkistatVsUserLogin = mkimodel ;
vm.Id = id;
return View(vm );
and in View set model to LoginVM:
#model ABCoLtd.ViewModels.LoginVM
UPDATE:
you already have a viewmodel didnt noticed that, you just need to do this:
var mkimodel = new MkistatVsUserLogin
{
mkistats = dsedb.mkistats.ToList(),
sample_1 = id
};
return View(nkimodel);

After login you are directly redirecting your user to an action and that action you have not mentioned here.And that action whose view you have shown is an strongly typed view which expects a list of MkistatVsUserLogin. But, I think you are not passing that list, so Model property of view will remain null and that will be causing an error of object reference. Please check this issue.

I got it. I just made another method in controller for viewing table with user session.
[HttpPost]
public ActionResult Login(sample_1 id)
{
if (ModelState.IsValid)
{
var uservar = db.sample_1.Where(a => a.boid.Equals(id.boid)).FirstOrDefault();
if (uservar != null)
{
Session["UserBOID"] = uservar.boid.ToString();
return RedirectToAction("UserLogin");
}
}
return View(id);
}
public ActionResult UserLogin()
{
if(Session["UserBOID"] != null)
{
var mkimodel = new MkistatVsUserLogin { mkistats = dsedb.mkistats.ToList() };
return View(mkimodel);
}
else
{
return RedirectToAction("Login");
}
}

Related

Problem with checkbox helper returning null values ASP.NET MVC

Model:
public class ItemModel
{
public bool IsChecked { get; set; }
}
ViewModel:
public class CategoryItemViewModel
{
public List<ItemModel> Item { get; set; }
}
Index Controller:
public List<ItemModel> GetItemModel()
{
//Get fie path
var ItemFile = Server.MapPath("~/App_Data/Items.txt");
//Read from the Categories.txt file and display the contents in the List view
List<ItemModel> item = new List<ItemModel>();
//Read the contents of Category.txt file
string txtData = System.IO.File.ReadAllText(ItemFile);
//Execute a loop over the rows.
foreach (string row in txtData.Split('\n'))
{
if (!string.IsNullOrEmpty(row))
{
item.Add(new ItemModel
{
IsChecked = Convert.ToBoolean(row.Split(',')[0])
});
}
}
return item;
}
The code above is basically reading items in a text file and then setting them to the model.
I am having an issue when wanting to change the checked value of a checkbox, as the actual checkbox is returning a null value when I try check it, Problem code is below.
Controller to add a new line item with a checkbox:
[HttpPost]
public ActionResult Item(bool ItemCheck)
{
//Get file path of Categories.txt
var ItemFile = Server.MapPath("~/App_Data/Items.txt");
var ItemData = ItemCheck + Environment.NewLine;
System.IO.File.AppendAllText(ItemFile, ItemData);
return View();
}
bool ItemCheck is returning a null value.
Index View code:
foreach (var item in Model.Item)
{
#using (Html.BeginForm("Item", "Item", FormMethod.Post))
{
#Html.CheckBoxFor(ItemModel => ItemModel.IsChecked)
}
}
It is saying that ItemModel does not contain a definition for IsChecked.
This could be due to the following reasons
Referring wrong namespace for model, ItemModel. To ensure that you are using correct model use #model yourNamespace.ItemModel
Build issue. clean and build the project.

Use variable from controller in view ASP.NET MVC4

There is a model in my project
using System;
namespace Argussite.SupplierServices.ViewModels
{
public class UsersPage
{
public Guid SupplierId { get; set; }
public string SupplierFullName { get; set; }
public bool ActionsAllowed { get; set; }
}
}
I use my model in controller and set properties
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
//.Include(e => e.Supplier)
.FirstOrDefault(e => e.Id == id);
string SupplierId = id.ToString();
string SupplierFullName = supplierOfUser.FullName.ToString();
bool ActionsAllowed = supplierOfUser.Active;
return View();
}
and then I need to use that in view, but I don't know how to get my properties in the view?
Firstly your controller action needs to send that model instance to the view like this:
return View(supplierOfUser);
You need this at the top of your view:
#model Argussite.SupplierServices.ViewModels.UsersPage
Then all you need to do is whereever you want to use your model in the view do:
#Model.SupplierFullName
If you want to use other properties in the view that you can place them into a dynamic ViewBag variable like this:
ViewBag.supplierOfUser = supplierOfUser.FullName.ToString();
and then on your view you can use this value like this:
#ViewBag.supplierOfUser
Create a new UsersPage and assign the properties you already have to its properties, then pass the newly created UsersPage to the view:
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
//.Include(e => e.Supplier)
.FirstOrDefault(e => e.Id == id);
var usersPage = new UsersPage();
usersPage.SupplierId = id.ToString();
usersPage.SupplierFullName = supplierOfUser.FullName.ToString();
usersPage.ActionsAllowed = supplierOfUser.Active;
return View(usersPage);
}
In order to use your data from the controller to the view, you need to return the view with your model in parameter:
return View(supplierOfUser);
In your view, you'd also need to define the model:
#model YourModel
Note that you don't need to set your supplier info into other variables (only supplierOfUser is required).
Best way is to establish a strongly typed model in the view:
#model Argussite.SupplierServices.ViewModels.UsersPage
Then, just reference the properties on the model, e.g.
#Html.EditorFor(model => model.SupplierFullName)
It's hard to help you with exact code as I don't know what you want to do on your view, this is a general idea of how you're supposed to pass and use your model in your view
Controller
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
.FirstOrDefault(e => e.Id == id);
var usersPage = new UsersPage
{
SupplierId = supplierOfUser.Id,
SupplierFullName = supplierOfUser.FullName,
ActionsAllowed = supplierOfUser.Active
}
return View(usersPage ); // <-- Send viewmodel to view
}
VIEW
// Declare model
#model Argussite.SupplierServices.ViewModels.UsersPage
...
//Use your model here at will
#Html.DisplayFor(modelItem => item.FullName)
...
#Html.EditorFor(model => model.FullName)
#Html.ValidationMessageFor(model => model.FullName)

Show images from IQueryable in View

I have a question about showing images loaded from a mysql database in a view.
In my database table "deliverables" I have "item_id", "deliverable_image" and "afstudeerrichting_id". "item_id" and "afstudeerrichting_id" are FK from other tables.
I want to show the images when afstudeerrichting_id = ..
Controller:
public ActionResult Index()
{
var model = repository.GetIdsOfImages(1);
return View(model.ToList());
}
public ActionResult ShowImage(int afstudeerrichtingid)
{
IQueryable<byte[]> data = repository.GetImages(afstudeerrichtingid);
var thedata = data.First();
return File(thedata, "image/png");
}
Repository (where I get the images):
public IQueryable<long> GetIdsOfImages(int afstudeerrichtingid)
{
return from deliverable in entities.deliverables
where deliverable.afstudeerichting_id.Equals(afstudeerrichtingid)
select deliverable.item_id;
}
public IQueryable<byte[]> GetImages(int afstudeerrichtingid)
{
return from deliverable in entities.deliverables
where deliverable.afstudeerichting_id.Equals(afstudeerrichtingid)
select deliverable.deliverable_image;
}
View:
#foreach(var imgID in Model.DeliverablesIDsList)
{
<img src="#Url.Action("ShowImage", "Deliverable", new { DeliverableID = imgID })" />
}
In my Viewmodel:
public List<long> DeliverablesIDsList { get; set; }
public int DeliverableID { get; set; }
Now I get the error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[System.Int64]', but this dictionary requires a model item of type 'GDMfrontEnd.Models.DeliverableViewModel'.
What should I change in my ViewModel? Or what am I doing wrong?
You can do that:
1) pass to the view a list of images' ids, and build list like this
#foreach(var imgId in model.ImgIdsList)
{
<img src="#Url.Action("ShowImage", "Deliverable", new { imageId = imgId })" />
}
2) in controller, which open this view, simply build a ImgIdsList (probably you need a GetIdsOfImagesWithAfstudeerichtingid(int afstudeerrichtingid), which would return a list of int)
3) you should your ShowImage method - not pass afstudeerrichtingid, but unique id of image; of course in this method you should method like GetImageById(int id).

Model View referring to null reference

I have a view page with multiple models and i am having trouble getting the data to display but i could save any added data just fine. It is just displaying the data on page load tells me that the model i am passing in passes a null reference.
Main view:
#model Project.Models.ProfileModel
#{
ViewBag.Title = "Profile";
}
<hgroup class="title">
<h1>#ViewBag.Title.</h1>
</hgroup>
<div id="wrap">
<div id ="right">
#(ViewBag.HasLocalPassword ? Html.Partial("_ChangePasswordPartial", Model.PasswordModel) : Html.Partial("_SetPasswordPartial", Model.PasswordModel))
</div>
<div id="left">
#Html.Partial("_UsernamePartial", Model.UsernameModel)
#Html.Partial("_PlayNamePartial", Model.PlayNameModel)
</div>
</div>
My models:
public class ProfileModel
{
public PasswordModel PasswordModel { get; set; }
public PlayNameModel PlayNameModel { get; set; }
public UsernameModel UsernameModel { get; set; }
}
Controller - For each model i have a get and post method except the PlayName just has a GET.
UserName Controller:
public ActionResult _UsernamePartial()
{
var usernameModel = new UsernameModel();
using (var db = new DataContext())
{
usernameModel.Username =
(from u in db.Users where u.ID == WebSecurity.CurrentUserId select u.Username).FirstOrDefault();
}
return PartialView(usernameModel);
}
#Html.Partial("_UsernamePartial", Model.UsernameModel) shows Object reference not set to an instance of an object. and i am not sure how to properly fix this.
public ActionResult Profile(ManageMessageId? message)
{
ViewBag.StatusMessage =
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
: message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
: "";
ViewBag.HasLocalPassword = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
ViewBag.ReturnUrl = Url.Action("Profile");
return View();
}
Post for Username:
[HttpPost]
public ActionResult _UsernamePartial(UsernameModel usernameModel)
{
if (ModelState.IsValid)
{
using (var db = new DataContext())
{
User user = db.Users.FirstOrDefault(u => u.ID == WebSecurity.CurrentUserId);
user.Username = usernameModel.Username;
db.SaveChanges();
}
}
return View("_UsernamePartial");
}
Username Page:
#model Acatar.Models.UsernameModel
#using (Html.BeginForm("_UsernamePartial", "Account")) {
<p id="legend">Username</p>
#Html.TextBoxFor(m=>m.Username)
<button type="submit" value=" Username">Save</button>
}
Your Null Ref was the result of View() Factory call without the bound model.
Use this code in Class
public virtual PasswordModel PasswordModel1
{
get {
PasswordModel PasswordModel2 = this.PasswordModel.FirstOrDefault();
if (PasswordModel2 == null)
{
PasswordModel2 = new PasswordModel();
}
return PasswordModel2;
}
}
use this code in view
#Html.Partial("_UsernamePartial", Model.UsernameModel, new ViewDataDictionary(Html.ViewDataContainer.ViewData)
{
TemplateInfo = new System.Web.Mvc.TemplateInfo { }
})
Do this For Other Model as well Hope It will help u.

MVC3- Passing an entire model with dynamic data from view to controller

I have two models: OuterModel and InnerModel. There is a one to many relationship between OuterModel and InnerModel, respectively. To clarify my question, my model is of type IEnumerable<OuterModel>. I'm passing a random number of OuterModels to the view and the user creates any number of InnerModels for each OuterModel. Then on submission, I want the controller to receive the list of OuterModels so that the InnerModels can be added to the database to their intended OuterModels.
I believe I have the naming convention correct to make use of MVC's built in model binding. Here's what that looks like:
OuterModel[i].InnerModel[j].Property
My problem is, I don't really know how to get a list of OuterModels passed to the controller. Here's what I've tried in my View:
#model IEnumerable<OuterModel>
#using (Html.BeginForm("Create", "Controller", new { OuterModels = Model }, FormMethod.Post))
{
//Code to create the InnerModels here
}
And here's what I have in my Controller:
[HttpPost]
public ActionResult Create(IEnumerable<OuterModel> OuterModels, FormCollection fc)
{
String[] keys = fc.AllKeys;
if(ModelState.IsValid){
//Add to db
}
}
Keys shows that all of my properties are following the naming convention that I specified earlier, but ModelState.IsValid is returning false. It shows that OuterModels' count is 0.
Even though I'm telling the form to submit OuterModels = Model before any InnerModels are created, you would think there would still be data in OuterModels considering it's passed to the view. I am really tired today, so I'm guessing I'm looking over one (or many) small detail(s). Any suggestions?
--EDIT--
Passing a list of OuterModels to the controller may not be the best approach. If anybody has a better suggestion, please share.
As long as indexes are used properly, then this should not be an issue. Here is how I would envision the form names.
Model[0].foo
Model[0].Inner[0].bar
Model[0].Inner[1].bar
Where outer model has a property called foo and
Outer model has a property called inner which is a collection of inner objects. Inner object has a property called bar. If your form is rendered with the correct indexes then the model binding should work. Things can get tricky if form fields are generated client side. I recommended going back to server in order to manipulate the model. There are some extra round trips, but you can make them via Ajax request.
Here are some more details in a more fleshed out example.
public class InnerModel{
public string Name{get; set;}
}
public class OuterModel{
public List<InnerModel> InnerModels{get; set;}
public string Name{get; set;}
}
Here is what I would envision my view would look like:
#model IEnumerable<OuterModel>
<ul>
#{int i = 0;}
#foreach(var item in Model){
<li>
Outer Name : #Html.TextBoxFor(m=>Model[i].Name)
<br />
#{int j = 0;}
<ul>
#foreach(var innerItem in Model[i].InnerModels){
<li>Inner Name : #Html.TextBoxFor(m=> Model[i].InnerModels[j].Name)</li>
j++;
}
</ul>
i++;
</li>
}
</ul>
If this is wrapped in a form--- and the controller action looks like this:
public ActionResult Action(List<OuterModel> model){
}
then I would think model would be populated correctly.
I noticed your form.. it doesn't look right to me... I wouldn't think that the passing the OuterModels like that is going to work-- although frankly I might be wrong.
#using (Html.BeginForm("Create", "Controller", new { OuterModels = Model }, FormMethod.Post))
{
//Code to create the InnerModels here
}
Here is an example I did for the class I teach.. that definitely works..
public class Author
{
public string Name { get; set; }
}
public class Book
{
public string Name { get; set; }
public List<Author> Authors { get; set; }
}
Controller:
public class BookController : Controller
{
public static List<Book> _model = null;
public List<Book> Model
{
get
{
if (_model == null)
{
_model = new List<Book>
{
new Book{
Name = "Go Dog Go",
Authors = new List<Author>{
new Author{Name = "Dr. Seuss"}
}},
new Book{
Name = "All the Presidents Men",
Authors = new List<Author>{
new Author{Name = "Woodward"},
new Author{Name = "Bernstein"}
}},
new Book{
Name = "Pro ASP.NET MVC Framework",
Authors = new List<Author>{
new Author{Name = "Sanderson"},
new Author{Name = "Stewart"},
new Author {Name = "Freeman"}
}}
};
}
return _model;
}
}
public ActionResult Index()
{
return View(Model);
}
public ActionResult Edit()
{
return View(Model);
}
[HttpPost]
public ActionResult Edit(List<Book> books)
{
_model = books;
return RedirectToAction("Index");
//return View(books);
}
}
and View:
#model List<AmazonWeb.Models.Book>
#{
ViewBag.Title = "Index";
}
<div class="content">
#Html.ActionLink("Index", "Index")
#using (Html.BeginForm())
{
<input type="submit" value="save" />
<ul class="book-list">
#for (var i = 0; i < Model.Count; i++ )
{
<li>
<label>Book Name</label> : #Html.TextBoxFor(m => Model[i].Name)
<ul>
#for (var j = 0; j < Model[i].Authors.Count; j++ )
{
<li><label>Author Name</label> : #Html.TextBoxFor(m => Model[i].Authors[j].Name)</li>
}
</ul>
</li>
}
</ul>
<input type="submit" value="save" />
}
</div>

Resources