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.
Related
I have searched some articles but none of them fits with my problem. i have this code in my cshtml
#model IEnumerable<MonitoreoIntegrado.Models.Sensores>
#using (Html.BeginForm("Graphics", "Datos_extensometro", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div style="margin:0; padding:0; border:none; position:absolute; bottom:5px; right:25px;"><input type="submit" id="enviar" class="btn btn-primary" value="Consultar"></div>
<div style="float:left; width:428px; height:105px; padding:5px; overflow-y: scroll;">
<h4 style="margin-top:0px;">Consultar multiples sensores</h4>
#foreach (var item in Model)
{
#Html.CheckBox("sensoresCB", false, new { value = #item.idSensor.ToString() }) #item.nombre <a class="moverse" objetivo="#(item.idSensor)" href=""><span class="glyphicon glyphicon-map-marker" title="Ir al marcador"></span></a><br />
}
</div>
}
and this in my controller:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = RolesSistema.Administrador + "," + RolesSistema.Lectura)]
public ActionResult Graphics()
{
return View();
}
I need help to receive that checkboxes in my controller and check which of them are checked
You should use unique id's for your inputs. The easiest way:
#for (var i = 0; i < Model.Count(); i++)
{
#Html.CheckBox("sensoresCB["+i.ToString()+"]", false, new { value = Model[i].idSensor.ToString() })
//your other stuff
}
And on controller side:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = RolesSistema.Administrador + "," + RolesSistema.Lectura)]
public ActionResult Graphics(bool[] sensoresCB) //note this
{
return View();
}
So you got the array with your selections. Use index to understand what checkbox it is.
You could extend the model of item with a Checked property or similar.
public class GraphicsViewModel {
public GraphicsItemViewModel[] Items { get; set; }
}
public class GraphicsItemViewModel {
public bool Checked { get; set; }
public long IdSensor { get; set; }
}
Then you can render the checkbox with a binding to this Checked property.
#model GraphicsViewModel
#using (Html.BeginForm(/* ....*/) {
// use a for loop so the array is bound correctly
#for (int i = 0; i < Model.Items.Length; i++) {
#Html.CheckBoxFor(m => m.Items[i].Checked)
// post back IdSensor value so we can access it in the controller
#Html.HiddenFor(m => m.Items[i].IdSensor)
}
}
Your controller should accept a model for the POST data, you can reuse the ViewModel:
[HttpPost]
public ActionResult Graphics(GraphicsViewModel postData) {
bool areAllChecked = postData.Items.All(i => i.Checked);
bool isFirstChecked = postData.Items.First().Checked;
bool isCertainIdChecked = postData.Items.Single(i => i.IdSensor == 1337).Checked;
// ...
}
I would like to mention a helpful point here, that is
If a checkbox is checked, then the postback values will contain a
key-value pair of the form [InputName]=[InputValue]
If a checkbox is not checked, then the posted form contains no
reference to the checkbox at all.
So in a controller action method, you can use the name of the checkbox and get the values which is only checked
ex:
public ActionResult Graphics(bool[] sensoresCB)
{
return View();
}
Hope above information was helpful
Thanks
Karthik
Based on #teo van kot reply I achieved to recover the checkboxes values. This is my working code.
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = RolesSistema.Administrador + "," + RolesSistema.Lectura)]
public ActionResult Graphics(int[] sensoresCB)//you can receive a string[] as well
{
//code and stuff
return View();
}
View:
#model IEnumerable<MonitoreoIntegrado.Models.Sensores>
#using (Html.BeginForm("Graphics", "Datos_extensometro", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
//some code stuff
#{
int i = 0;
foreach (var item in Model)
{
#Html.CheckBox("sensoresCB[" + i.ToString() + "]", false, new { value = item.idSensor.ToString() }) #item.nombre<br />
i++;
}
}
}
My case looks like this:
Model:
public class Book
{
public string Id { get; set; }
public string Name { get; set; }
}
public class Comment
{
public string Id { get; set; }
public string BookId { get; set; }
public string Content { get; set; }
}
Controller:
public IActionResult Detail(string id)
{
ViewData["DbContext"] = _context; // DbContext
var model = ... // book model
return View(model);
}
View:
Detail view:
#if (Model?.Count > 0)
{
var context = (ApplicationDbContext)ViewData["DbContext"];
IEnumerable<Comment> comments = context.Comments.Where(x => x.BookId == Model.Id);
#Html.Partial("_Comment", comments)
}
Comment partial view:
#model IEnumerable<Comment>
#if (Model?.Count > 0)
{
<!-- display comments here... -->
}
<-- How to get "BookId" here if Model is null? -->
I've tried this:
#Html.Partial("_Comment", comments, new ViewDataDictionary { { "BookId", Model.Id } })
Then
#{
string bookid = ViewData["BookId"]?.ToString() ?? "";
}
#if (Model?.Count() > 0)
{
<!-- display comments here... -->
}
<div id="#bookid">
other implements...
</div>
But error:
'ViewDataDictionary' does not contain a constructor that takes 0
arguments
When I select ViewDataDictionary and press F12, it hits to:
namespace Microsoft.AspNetCore.Mvc.ViewFeatures
{
public ViewDataDictionary(IModelMetadataProvider metadataProvider, ModelStateDictionary modelState);
}
I don't know what are IModelMetadataProvider and ModelStateDictionary?
My goal: Send model comments from view Detail.cshtml to partial view _Comment.cshtml with a ViewDataDictionary which contains BookId.
My question: How can I do that?
Another way to use this is to pass the ViewData of the current view into the constructor. That way the new ViewDataDictionary gets extended with the items you put in using the collection initializer.
#Html.Partial("MyPartial", new ViewDataDictionary(ViewData) { { "BookId", Model.Id } })
Use the following code to create a ViewDataDictionary
new ViewDataDictionary(new Microsoft.AspNetCore.Mvc.ModelBinding.EmptyModelMetadataProvider(), new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary()) { { "BookId", Model.Id } }
On .NET Core I use ViewDataDictionary with a parameter, like:
#Html.Partial("YourPartial", new ViewDataDictionary(ViewData) { { "BookId", Model.Id } })
I'm passing objects to the Layout from the controller like this:
public ActionResult MyProfile()
{
var roles = new List<int?>();
User.Roles.ForEach(r => roles.Add(r.ID));
return View(new ProfileModel()
{
LoginUser = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string.IsNullOrEmpty(User.LastName) ? string.Empty : User.LastName.ToLower()),
UserRole = new List<int?>(roles)
});
}
public class ModelBase {
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string LoginUser { get; set; }
public List<int?> UserRole { get; set; }
public ModelBase() {
UserRole = new List<int?>();
}
}
public class ProfileModel : ModelBase { }
This works but, I have to do this for all my Controller Action when returning a view because I need the roles and login user on all my views.
Is there a way for me to do this just once, without having to repeat it in my actions?
I try adding to it to a base controller, but ROLES and LOGINUSER were always null.
I know this has been addressed a lot on SO, but they are all doing the something.
Thanks.
Using Stephen Muecke suggestion I did this:
[ChildActionOnly]
public PartialViewResult Navigation() {
return PartialView("_Navigation", new LayoutModel(User));
}
[ChildActionOnly]
public PartialViewResult LoginInfo() {
return PartialView("_LoginInfo", new LoginInfoModel(User));
}
And
<div class="collapse navbar-collapse" id="navbar-collapse-area">
#Html.Action("LoginInfo", "Home")
</div>
<div class="col-lg-2 sidebox">
<div class="sidebar content-box" style="display: block;">
#Html.Action("Navigation", "Home")
</div>
</div>
Bernard's suggestion also works, but i prefer this.
Try this:
public ActionResult MyProfile()
{
var roles = new List<int?>();
User.Roles.ForEach(r => roles.Add(r.ID));
return View(new ProfileModel(User));
}
Model:
public class ModelBase
{
public ModelBase(User user) {
UserRole = new List<int?>();
LoginUser = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string.IsNullOrEmpty(user.LastName) ? string.Empty : user.LastName.ToLower()),
}
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string LoginUser { get; set; }
public List<int?> UserRole { get; set; }
}
ProfileModel:
public class ProfileModel : ModelBase
{
public ProfileModel(User user) : base(user) { }
}
I think it is not a bad practice to write some code in your layout. If it is a razor view or something similar you can add user name and its roles directly in the view.
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");
}
}
I have a question about showing images loaded from a mysql database in an Index 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 id)
{
IQueryable<byte[]> data = repository.GetImages(id);
byte[] firstimage = data.First();
return File(firstimage, "image/png");
}
Repository:
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 itemID)
{
return from deliverable in entities.deliverables
where deliverable.item_id.Equals(itemID)
select deliverable.deliverable_image;
}
View:
#foreach(var imgID in Model.DeliverablesIDsList)
{
<img src="#Url.Action("ShowImage", "Deliverable", new { DeliverableID = imgID })" />
}
In my Viewmodel I have:
public List<long> DeliverablesIDsList { get; set; }
public int DeliverableID { get; set; }
But now I always get this error:
he 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'.
Does someone knows what I'm doing wrong?
you're sending to the view a list of int64 repository.GetIdsOfImages(1).ToList() and the view requires a DeliverableViewModel, so you must create a model and put the list into the model and send it to the view
the action should looks like:
public ActionResult Index()
{
var model = repository.GetIdsOfImages(1);
DeliverableViewModel model = new DeliverableViewModel()
model.DeliverablesIDsList = repository.GetIdsOfImages(1).ToList();
return View(model); //send to the view a model type of DeliverableViewModel
}
now with ActionResult ShowImage, the action expect id parmeter and you're sending DeliverableID, so change de var name
public ActionResult ShowImage(int DeliverableID)
{
IQueryable<byte[]> data = repository.GetImages(DeliverableID);
byte[] firstimage = data.First();
return File(firstimage, "image/png");
}