asp.net mvc querying from different table to view - asp.net

I need to query data from 2 table
public class UserProfile
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
}
and
public class PrivateMessage
{
public int MessageId { get; set; }
public string Sender { get; set; }
public string Receiver { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
private DateTime _date = DateTime.Now;
public DateTime sentDate { get { return _date; } set { _date = value; } }
}
and this what i tried on my controller
public ActionResult Index()
{
var x = User.Identity.Name;
var query = from p in db.PrivateMessages
join u in db.UserProfiles on p.Sender equals u.UserName
where p.Receiver == x
select new
{
u.UserName,
u.Name,
p.Receiver,
p.Subject,
p.Message,
p.sentDate
};
return View(query);
}
this is my view model
#model IEnumerable<SeedSimple.Models.PrivateMessage>
but i got this error
The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType95[System.String,System.String,System.String,System.String,System.DateTime]]',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable`1[SeedSimple.Models.PrivateMessage]'.
all i want is to get username and name from UserProfile table and receiver, subject, message and sentDate on PrivateMessage table

Well you're passing as a Model an anonymous type yet you have a strongly typed View.
You can either create a new ViewModel that contains all the fields you're using for your query and pass that, or you can pass all the properties in the ViewBag (not a pretty solution).
EDIT
Thought I'd give you an example.
Here is a ViewModel containing the data you need:
public class MessageViewModel
{
public string UserName { get; set; }
public string Name { get; set; }
public string Receiver { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
public DateTime SentDate { get; set; }
}
In your view:
#model IEnumerable<SeedSimple.Models.MessageViewModel>
In your Controller:
public ActionResult Index()
{
var x = User.Identity.Name;
var result = from p in db.PrivateMessages
join u in db.UserProfiles on p.Sender equals u.UserName
where p.Receiver == x
select new MessageViewModel
{
UserName = u.UserName,
Name = u.Name,
Receiver = p.Receiver,
Subject = p.Subject,
Message = p.Message,
SentDate = p.sentDate
};
return View(result);
}
I hope this helps.

Related

How skip NullReferenceException in Get API

Here create an API to get the records, in my entity relation table there are twice start date and end date. Here my compulsion is one of them need to keep Null able type.
Here is ER that is SchoolCourses:
public class SchoolCourses
{
public Guid ID { get; set; }
public DateTime StartCourseDate { get; set; }
public DateTime EndCourseDate { get; set; }
public DateTime? StartSemDate { get; set; } // Null able type
public DateTime? EndSemDate { get; set; } // Null able type
}
I creates a repository for getting the value:
public async Task<ICollection<SchoolCourses>> GetcourseBySchoolId(Guid SchoolId)
{
List<SchoolCourses> schoolCourses = null;
schoolCourses = await _GpsContext.SchoolCourses.AsNoTracking()
.Where(x => x.SchoolsID == SchoolId)
.ToListAsync();
return schoolCourses;
}
And the Controller are like this:
public async Task<IActionResult> GetforSchoolCourse(string SchoolId)
{
var result = await _schoolCoursesRepository.GetcourseBySchoolId(Guid.Parse(SchoolId));
List<GetSchoolCourseBySchoolIdVm> getSchoolCourseBySchoolIdVms = new List<GetSchoolCourseBySchoolIdVm>();
foreach (SchoolCourses schoolCourse in result)
{
getSchoolCourseBySchoolIdVms.Add(new GetSchoolCourseBySchoolIdVm
{
id = schoolCourse.ID.ToString(),
StarCoursetDate = schoolCourse.StartCourseDate.ToString(),
EndCourseDate = schoolCourse.EndCourseDate.ToString(),
StartSemDate = schoolCourse.StartSemDate.ToString(),
EndSemDate = schoolCourse.EndSemDate.ToString(),
});
}
return Ok(getSchoolCourseBySchoolIdVms);
}
Here is View Model for reference:
public class GetSchoolCourseBySchoolIdVm
{
public string id { get; set; }
public string StarCoursetDate { get; set; }
public string EndCourseDate { get; set; }
public string StartSemDate { get; set; }
public string EndSemDate { get; set; }
}
After doing all the above staff it is getting exception error in swagger is following:
System.NullReferenceException: Object reference not set to an instance of an object.;
In your SchoolCourses model StartSemDate and EndSemDate are nullable types, so it must be possible that values of those fields are null. That should have been checked before using it, unlike you have used
StartSemDate = schoolCourse.StartSemDate.ToString(),
EndSemDate = schoolCourse.EndSemDate.ToString(),
here if any of the date is null then calling .ToString() method on it will throw NullReferenceException. Use safe navigation operator to check
schoolCourse.StartSemDate?.ToString()
or
schoolCourse.StartSemDate != null ? schoolCourse.StartSemDate.ToString() : string.Empty

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ConsoleUserInfoes_dbo.ConsolesCheckBoxes_consoleId"

I'm getting this error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ConsoleUserInfoes_dbo.ConsolesCheckBoxes_consoleId". The conflict occurred in database "aspnet-ForePlay-20180525122039", table "dbo.ConsolesCheckBoxes", column 'ConsoleId'.
I'm using Entity Framework and ASP.NET MVC 5 and IdentityUser and try to insert data form checkListBox to table into my database.
This is happening on the register view, when user need to register and fill the form.
public class ConsoleUserInfo
{
[Key]
public int identity { get; set; }
[Required]
[StringLength(255)]
[ForeignKey("User")]
public string userid { get; set; }
[Required]
[ForeignKey("consolesCheckBox")]
public int consoleId { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ConsolesCheckBox consolesCheckBox { get; set; }
}
This is the table that need to get a user id (form applictionUser) and consoleId
(form ConsolesCheckBox )
This is the ApplicationUserUser model class:
public class ApplicationUser : IdentityUser
{
[Required]
[StringLength(255)]
override
public string UserName { get; set; }
[Required]
[StringLength(50)]
public string Phone { get; set; }
public byte[] UserPhoto { get; set; }
public virtual UserAddress Address { get; set; }
public virtual ICollection<ConsolesCheckBox> consoleCheckBox { get; set; }
}
and this is the checkBoxList table:
public class ConsolesCheckBox
{
[Key]
public int ConsoleId { get; set; }
public string ConsoleName { get; set; }
public bool IsChecked { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
This is my account controller, all in the register get and post
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register()
{
//using database
using (ApplicationDbContext dbo = new ApplicationDbContext())
{
//data will save list of the consoleCheckBoxItem
var data = dbo.consolesCheckBox.ToList();
// because the view is request a common model, we will create new one
CommenModel a = new CommenModel();
a.ConsolesCheckBoxList = data;
// we will need to return common model, that way we will return a
return View(a);
}
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register([Bind(Exclude = "UserPhoto")]CommenModel model)
{
if (ModelState.IsValid)
{
// To convert the user uploaded Photo as Byte Array before save to DB
byte[] imageData = null;
if (Request.Files.Count > 0)
{
HttpPostedFileBase poImgFile = Request.Files["UserPhoto"];
using (var binary = new BinaryReader(poImgFile.InputStream))
{
imageData = binary.ReadBytes(poImgFile.ContentLength);
}
}
var user = new ApplicationUser
{
UserName = model.registerViewModel.Email,
Email = model.registerViewModel.Email,
Phone = model.registerViewModel.Phone
};
user.UserPhoto = imageData;
var result = await UserManager.CreateAsync(user, model.registerViewModel.Password);
//after the user create, we will use the id and add the id to the userAddress table include
// Address, longitude and latitude.
using (ApplicationDbContext dbo = new ApplicationDbContext())
{
var currentUserId = user.Id;
var pasinfo = dbo.userAddress.FirstOrDefault(d => d.Userid == currentUserId);
if (pasinfo == null)
{
pasinfo = dbo.userAddress.Create();
pasinfo.Userid = currentUserId;
dbo.userAddress.Add(pasinfo);
}
pasinfo.Address = model.useraddress.Address;
pasinfo.latitude = model.useraddress.latitude;
pasinfo.longitude = model.useraddress.longitude;
dbo.SaveChanges();
foreach (var item in model.ConsolesCheckBoxList.Where(x => x.IsChecked).Select(x => x.ConsoleId))
{
var consoleUserInfo = new ConsoleUserInfo
{
userid = currentUserId,
consoleId = item
};
dbo.consoleUserInfo.Add(consoleUserInfo);
}
dbo.SaveChanges();
}
}
}
In the register GET I have a common model, because I used 3 models in the view
this is the common model:
public class CommonModel
{
public UserAddress useraddress { get; set; }
public RegisterViewModel registerViewModel { get; set; }
public List<ConsolesCheckBox> ConsolesCheckBoxList { get; set; }
}
I need your help here, I've been trying to fix this all day.

How to join my tables with identity tables?

I started a default MVC project with Identity and EF.
In my app users will be able to create and edit some records.
In the table for these records, I want to have the ids of users who created the record and who updated lastly.
My model class is like:
public class Record
{
public int ID { get; set; }
public DateTime CreateTime { get; set; }
public string CreatingUserID { get; set; }
public string UpdatingUserID { get; set; }
public DateTime UpdateTime { get; set; }
public Enums.RecordStatus Status { get; set; }
}
And in RecordsController, I save new records to db like this:
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(FormCollection form, RecordCreateVM vm)
{
string userId = User.Identity.GetUserId();
DateTime now = DateTime.Now;
Record rec = new Record ();
if (ModelState.IsValid)
{
int newRecordId;
using (RecordRepository wr = new RecordRepository())
{
UpdateModel(rec);
rec.CreateTime = now;
rec.UpdateTime = now;
rec.CreatingUserID = userId;
rec.UpdatingUserID = userId;
rec.Status = Enums.RecordStatus.Active;
Record result = wr.Add(rec);
wr.SaveChanges();
newRecordId = result.ID;
}
}
}
When I am listing these records, I also want my page to display these users' usernames.
I get all the active records from the repository I created.
public ActionResult Index()
{
RecordListVMviewModel = new RecordListVM();
using (RecordRepository wr = new (RecordRepository())
{
viewModel.Records = wr.GetAll();
}
return View(viewModel);
}
And this is the repository code:
public class RecordRepository: Repository<Record>
{
public override List<Record> GetAll()
{
IQueryable<Record> activeRecords = DbSet.Where(w => w.Status == Enums.RecordStatus.Active);
return activeRecords.ToList();
}
}
Where do I have to make changes? Can you give me an sample code for usages like this?
Thank you.
You need to change
public string CreatingUserID { get; set; }
public string UpdatingUserID { get; set; }
to something like:
public User CreatingUser { get; set; }
public User UpdatingUser { get; set; }
Set the ID's during the creation of new RecordRepository()
Then access them as Record.CreatingUser.FirstName ect

asp.net mvc - how to save a model with enum fields?

My model is defined as follows:
namespace Project.Models
{
public enum LogType
{
Login = 0,
Login_Fail = 1
}
[Table("UserLog")]
public class UserLog
{
public long Id { get; set; }
public int UserId { get; set; }
public DateTime Date { get; set; }
public string Des { get; set; }
public LogType Type { get; set; }
public virtual User User { get; set; }
}
}
Base type of Type field in the UserLog table is tinyint.
Login controller code as follows:
[HttpPost]
public virtual JsonResult Login(UserViewModel model)
{
if (userRepository.CheckUserLogin(model.UserName, model.Password))
{
UserLog log = new UserLog();
log.Date = DateTime.Now;
log.Des = "";
log.Type = LogType.Login;
userRepository.AddUserLog(model.UserName, log);
userRepository.Save();
Session["LoginUser"] = model.UserName;
}
}
And Login Repository code as follows:
public void AddUserLog(string username, UserLog log)
{
User user = GetUserByUserName(username);
if (user != null)
user.UserLogs.Add(log);
}
The problem is that information is properly stored in UserLog table, but the Type field remains Null!
I've used this solution:
public int Type { get; set; }
[NotMapped]
public LogType UserLogType
{
get { return (LogType)Type; }
set { Type = (int)value; }
}

MVC 5 Multiple Models in a Single View

Could somebody please provide an example of how to combine two models within one view?
Currently I have a page called RecordCard which contains:
#model IEnumerable<WebApplication1.Models.Weight>
This is provided by the following code in the AccountController:
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
return View(weightModel);
}
The RecordCard page also contains a form which is bound to the following class:
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
However, these are two individual models with different purposes, so how do I combine to a single model that contains an IEnumerable list and set of form elements that will ultimately post to the AccountController correctly to add a record to the database using the following code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(Weight Model)
{
if (ModelState.IsValid)
{
using (WebApplication1Entities db = new WebApplication1Entities())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return View(Model);
}
I have included the Weight class below:
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
Also here is the WebApplication1Entities class which declares the Weight table as Weights:
public partial class WebApplication1Entities : DbContext
{
public WebApplication1Entities()
: base("name=WebApplication1Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Weight> Weights { get; set; }
}
Please explain what needs to be modified and how, no matter what I try to read, follow and implement, I seem to be missing something.
Any help would be much appreciated :-)
I would say this is good example of using ViewModel here. I would suggest something like -
Create ViewModel with the composition of the two classes
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
....
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
.....
public class WeightViewModel
{
public IList<AddWeightModel> AddWeightModel { get; set; }
public Weight Weight { get; set; }
}
Then change your view to accept the view models -
#model WeightViewModel
Finally modify your controller to cope with the change -
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
var viewModel = new WeightViewModel
{
Weight = weightModel,
AddWeightModel = new List<AddWeightModel>(){}
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(WeightViewModel viewModel)
{
Weight Model = viewModel.Weight;
if (ModelState.IsValid)
{
using (WebApplication1Entities db = new WebApplication1Entities())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return RedirectToAction("RecordCard");
}
I've tackled this before, can came to an elegant solution.
First, you'd want to setup your main classes to send, as well as a 'holder' class to store them to eventually send to a view.
As you probably found out, this is because a view can't have multiple models sent to it.
public class WebsiteTheme
{
public string Color { get;set; }
public string Title { get;set; }
public WebsiteTheme() {
Color = "blue";
Title = "test website";
}
}
public class User
{
public string Name { get;set; }
public string Gender { get;set; }
public User() {
Name = "Anonymous";
Gender = "Unspecified";
}
}
public class ToPage
{
public WebsiteTheme WebsiteTheme{ get; set; }
public User User { get; set; }
public ToPage() {
websiteTheme = new WebsiteTheme();
user = new User();
}
}
This will allow you to send any amount of classes to your page.
Then, in your controller, you'd want to populate those classes. Make sure to initialise them all first, then set the populated classes to your holder class.
WebsiteTheme websiteTheme = new WebsiteTheme();
websiteTheme.Color = "orange";
User user = new User();
user.Name = "Darren";
ToPage toPage = new ToPage();
toPage.User = user;
toPage.WebsiteTheme = websiteTheme;
return View(toPage);
In your view, you'd call them in any way you want to. But make sure to use HolderModel.SpecifiedModel in every case.
#model WebApplication1.Models.ToPage
#Html.DisplayFor(model => model.User.Name)
I did a compound model like this:
public class CompoundModel
{
public SearchModel SearchModel { get; set; }
public QueryResultRow ResultModel { get; set; }
}
public class QueryResultRow
{
[DisplayName("Id")]
public long id { get; set; }
[DisplayName("Importdatum")]
public System.DateTime importdate { get; set; }
[DisplayName("Mandant")]
public int indexBMClient { get; set; }
}
public class SearchModel
{
[Required]
[DataType(DataType.Date)]
[Display(Name = "Zeitraum von")]
public DateTime dateFrom { get; set; }
[Display(Name = "Terminal-ID")]
public string tid { get; set; }
[Display(Name = "Belegnummer")]
public string receiptnumber { get; set; }
}
In the view header:
#model MyProject_aspmvc.Models.CompoundModel
And get data access from the SearchModel, for example:
model => model.SearchModel.tid
and data access from the ResultModel, for example:
model => model.ResultModel.importdate

Resources