Object reference not set to an instance of an object in Entity Framework - asp.net-mvc-5

I got question on this error which I cannot solve. I am using Entity Framework database first. And before that I have deleted the entity model and create a new one. I am not sure it will affect or not.
This is my viewModel
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
namespace MVCTutorial.Models
{
public class OtherIncViewModel
{
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<UserGroup> UserGroups { get; set; }
public virtual DbSet<Patient> Patients { get; set; }
//User
public int UserId { get; set; }
public string UserFullName { get; set; }
public string UserIC { get; set; }
[DataType(DataType.Password)]
[Required(ErrorMessage = "This field is requiered.")]
public string UserPassword { get; set; }
public string UserEmail { get; set; }
public Nullable<int> UserGroupId { get; set; }
public string UserMMCRegistrationNo { get; set; }
[DisplayName("UserName")]
[Required(ErrorMessage = "This field is requiered.")]
public string UserLogin { get; set; }
public string UserFaxNo { get; set; }
public string UserDesignation { get; set; }
public string UserStatus { get; set; }
public string UserContact { get; set; }
public virtual UserGroup UserGroup { get; set; }
public string LoginErrorMessage { get; set; }
//Patient
public int PatientId { get; set; }
public string PatientName { get; set; }
public string PatientIC { get; set; }
public int PatientAge { get; set; }
public string PatientGender { get; set; }
public string Hospital { get; set; }
public string Ward { get; set; }
public string Department { get; set; }
public string Barcode { get; set; }
public string Race { get; set; }
public string PatientErrorMessage { get; set; }
public virtual ICollection<CaseOtherInc> CaseOtherIncs { get; set; }
public virtual ICollection<DraftCaseOtherInc> DraftCaseOtherIncs { get; set; }
}
}
This is my controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVCTutorial.Models;
namespace MVCTutorial.Controllers
{
public class WardStaffController : Controller
{
OtherIncContext db = new OtherIncContext();
// GET: WardStaff
public ActionResult Index() //Ward Staff Inbox
{
return View();
}
public ActionResult CreateTransfusion() //Ward Staff Create Transfusion
{
return View();
}
public ActionResult CreateIBCT() //Ward Staff Create IBCT
{
return View();
}
public ActionResult CreateNearMiss() //Ward Staff Create Near Miss
{
return View();
}
[HttpPost]
public ActionResult SearchPatient(MVCTutorial.Models.OtherIncViewModel patient)
{
using (OtherIncContext db = new OtherIncContext())
{ //I am wondering here why my local variable does not reference the namespace in this case is MVCTutorial. Is this why i get the null exception? I have check my database...i didn't have null record.
var patientDetails = db.Patients.Where(x => x.PatientIC == patient.PatientIC).FirstOrDefault();
if (patientDetails == null)
{
patient.PatientErrorMessage = "Please enter patient's IC number.";
return View("CreateOtherIncident", patient);
}
else
{
Session["PatientName"] = patientDetails.PatientName;
}
return RedirectToAction("CreateOtherIncident", "WardStaff");
}
}
This is my view
#model MVCTutorial.Models.OtherIncViewModel
#{
ViewBag.Title = "CreateOtherIncident";
Layout = "~/Views/Shared/_LayoutWardStaff.cshtml";
}
<h2>CreateOtherIncident</h2>
<h2>Reported By:</h2>
<p> Name: #Session["UserFullName"].ToString()</p>
<p>Email Address: #Session["UserEmail"].ToString()</p>
<p>Date:</p>
<p>Designation No.: #Session["UserDesignation"].ToString()</p>
<p>Tel.No: #Session["UserContact"].ToString()</p>
<p>Fax.No: #Session["UserFaxNo"].ToString()</p>
<h2>Patient Details:</h2>
#Html.LabelFor(model=>model.PatientIC)
#Html.EditorFor(model=>model.PatientIC)
<p>Patient Name: #Session["PatientName"].ToString()</p> //I get the exception here.
I suspect it is because of the local variable, but I cannot find any further error or exception on that.

Before the exception, To check session should not be null.
like:
#if (HttpContext.Current.Session["PatientName"] != null)
{ //#Session["PatientName"].ToString()
}

Related

EF Core with AutoMapper

I have a DTO containing properties and a Model, eg student can have more than one module and a module can be associated with more than one student. the properties are mapping fine but the Model doesn't map.
public class GetStudentByIdMapping : Profile
{
public GetStudentByIdMapping()
{
CreateMap<Student,StudentDetails>();
CreateMap<Module, StudentDetails>()
.ForPath(dest => dest.StudentModules.ModuleName, opt => opt.MapFrom(m => m.ModuleName))
.ForPath(dest => dest.StudentModules.ModuleCode, opt => opt.MapFrom(m => m.ModuleCode))
.ForPath(dest => dest.StudentModules.Description, opt => opt.MapFrom(m => m.Description))
.ReverseMap();
}
}
public async Task<StudentDetails> GetStudent(int studentId)
{
var student = context.Student
.Where(s => s.StudentId == studentId)
.FirstOrDefault();
var module = await context.Order
.Include(m => m.Module)
.Where(o => o.StudentId == studentId)
.Select(m => m.Module).ToListAsync();
var studMap = Mapper.Map<StudentDetails>(student);
Mapper.Map<StudentDetails>(module);
return studMap;
}
These are the ViewModels I want to map to the Models Model in the StudentDetails ViewModel
public class StudentDetails
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public StudentModule StudentModules { get; set; }
}
public class StudentModule
{
public string ModuleName { get; set; }
public string ModuleCode { get; set; }
public string Description { get; set; }
}
These are my Entities generated by EF Core
public partial class Student
{
public Student()
{
Order = new HashSet<Order>();
}
public int StudentId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public virtual ICollection<Order> Order { get; set; }
}
public partial class Module
{
public Module()
{
Order = new HashSet<Order>();
}
public int ModuleId { get; set; }
public int? LectureId { get; set; }
public string ModuleName { get; set; }
public string ModuleCode { get; set; }
public string Description { get; set; }
public string ModulePath { get; set; }
public virtual Lecture Lecture { get; set; }
public virtual ICollection<Order> Order { get; set; }
}
You only need to pass the created destination to the second map call:
Just try the following code when mapping:
var studMap = Mapper.Map<Student,StudentDetails>(student);
Mapper.Map<Module,StudentDetails>(module,studMap);
Then the studMap will receive all mapped fields value.

Configuring AutoMapper in ASP.NET Core

I am trying to use automapper 8.0.0 to fill a list of WorkViewModel.
This list is getting data from the Work class out of the database using entity framework.
How ever it looks like something is going wrong with initializing as throwing follows error:
InvalidOperationException: Mapper not initialized
What am I doing wrong?
I have setup the following code!
Startup.cs
services.AddAutoMapper();
Function being called:
public async Task<IEnumerable<WorkViewModel>> GetAllAsync()
{
IList<Work> works = await _context.Work.ToListAsync();
IList<WorkViewModel> viewModelList = Mapper.Map<IList<Work>, IList<WorkViewModel>>(works);
return viewModelList;
}
Configuration:
public class MappingProfile : Profile
{
public MappingProfile()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<WorkViewModel, Work>();
});
}
}
WorkViewModel:
public class WorkViewModel
{
public int WorkID { get; set; }
public string Name { get; set; }
public byte[] Tumbmail { get; set; }
public string Discription { get; set; }
public string Client { get; set; }
public DateTime Date { get; set; }
public string PreviewLink { get; set; }
public string GitLink { get; set; }
public string DownloadLink { get; set; }
public int DetailID { get; set; }
public byte[] Banner { get; set; }
public string Documentation { get; set; }
public int CategoryID { get; set; }
public string Category { get; set; }
}
Work Model:
public class Work
{
[Key]
public int WorkID { get; set; }
[Display(Name = "Project Name")]
public string Name { get; set; }
[Display(Name = "Client name")]
public string Client { get; set; }
[Display(Name = "Description")]
public string Discription { get; set; }
[Display(Name = "Date")]
public DateTime Date { get; set; }
[Display(Name = "Thumbmail")]
public byte[] Tumbmail { get; set; }
[Display(Name = "Preview Link")]
public string PreviewLink { get; set; }
[Display(Name = "Git Link")]
public string GitLink { get; set; }
[Display(Name = "DownloadLink")]
public string DownloadLink { get; set; }
public WorkCategory workCategory { get; set; }
public WorkDetailed WorkDetailed { get; set; }
}
Only adding services.AddAutoMapper(); to the ConfigureServices method would not work for you. You have to configure AutoMapper as follows:
public void ConfigureServices(IServiceCollection services)
{
// Auto Mapper Configurations
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingProfile());
});
IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
services.AddMvc();
}
And also don't forget to install the AutoMapper.Extensions.Microsoft.DependencyInjection nuget package.

Complex Automapper Configuration

I'm mapping from an existing database to a DTO and back again use Automapper (4.1.1) and I've hit a few small problems.
I have a (simplified) model for the database table:
public class USER_DETAILS
{
[Key]
public string UDT_LOGIN { get; set; }
public string UDT_USER_NAME { get; set; }
public string UDT_INITIALS { get; set; }
public string UDT_USER_GROUP { get; set; }
public decimal UDT_CLAIM_LIMIT { get; set; }
public string UDT_CLAIM_CCY { get; set; }
}
and a DTO object:
public class User
{
public string Login { get; set; }
public string UserName { get; set; }
public string Initials { get; set; }
public string UserGroup { get; set; }
public double ClaimLimit { get; set; }
public string ClaimCurrency { get; set; }
}
I've created a profile
public class FromProfile : Profile
{
protected override void Configure()
{
this.RecognizePrefixes("UDT_");
this.ReplaceMemberName("CCY", "Currency");
this.SourceMemberNamingConvention = new UpperUnderscoreNamingConvention();
this.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
this.CreateMap<decimal, double>().ConvertUsing((decimal src) => (double)src);
this.CreateMap<USER_DETAILS, User>();
}
}
However, it seems that Automapper doesn't like combining this many settings in the config. Even simplifying the models, I can't get
this.RecognizePrefixes("UDT_");
this.ReplaceMemberName("CCY", "Currency");
to work together, and whilst
this.CreateMap<decimal, double>().ConvertUsing((decimal src) => (double)src);
works ok with the models in the test, it fails when using it against a database.
Is there a way to get all this to work together, or should I fall back to using ForMember(). I was really hoping I could get this working as there are a lot of tables in this system, and I'd rather not have to do each one individually.
You will need to extend this for other types, only tested with strings, I have an extension method that does all the work and looks for unmapped properties.
public class USER_DETAILS
{
public string UDT_LOGIN { get; set; }
public string UDT_USER_NAME { get; set; }
public string UDT_INITIALS { get; set; }
public string UDT_USER_GROUP { get; set; }
// public decimal UDT_CLAIM_LIMIT { get; set; }
public string UDT_CLAIM_CCY { get; set; }
}
public class User
{
public string Login { get; set; }
public string UserName { get; set; }
public string Initials { get; set; }
public string UserGroup { get; set; }
//public double ClaimLimit { get; set; }
public string ClaimCurrency { get; set; }
}
public static class AutoMapperExtensions
{
public static IMappingExpression<TSource, TDestination>
CustomPropertyMapper<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TSource);
var destinationType = typeof(TDestination);
var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType == sourceType && x.DestinationType == destinationType);
var properties = sourceType.GetProperties();
foreach (var property in existingMaps.GetUnmappedPropertyNames())
{
var similarPropertyName =
properties.FirstOrDefault(x => x.Name.Replace("_", "").Replace("UDT", "").ToLower().Contains(property.ToLower()));
if(similarPropertyName == null)
continue;
var myPropInfo = sourceType.GetProperty(similarPropertyName.Name);
expression.ForMember(property, opt => opt.MapFrom<string>(myPropInfo.Name));
}
return expression;
}
}
class Program
{
static void Main(string[] args)
{
InitializeAutomapper();
var userDetails = new USER_DETAILS
{
UDT_LOGIN = "Labi-Login",
UDT_USER_NAME = "Labi-UserName",
UDT_INITIALS = "L"
};
var mapped = Mapper.Map<User>(userDetails);
}
static void InitializeAutomapper()
{
Mapper.CreateMap<USER_DETAILS, User>().CustomPropertyMapper();
}
}
}

how do i use AutoMapper in ICollation<> Fields

when i use AutoMapper for mapping my ViewModels and get All News, thrown error for me.
Errors...
The following property on Mosque.Core.ViewModels.CategoryViewModel cannot be mapped:
Categories
Add a custom mapping expression, ignore, add a custom resolver, or modify the destination type Mosque.Core.ViewModels.CategoryViewModel.
please help me, thank you
//Models
public class News
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual User User { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<News> News { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<News> News { get; set; }
}
//ViewModels
public class NewsViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<CategoryViewModel> Categories { get; set; }
public virtual UserViewModel User { get; set; }
}
public class CategoryViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<NewsViewModel> News { get; set; }
}
public class UserViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<NewsViewModel> News { get; set; }
}
how do i use for select All News?
--Update1--
I used onion architecture in the project and i installed AutoMapper in the Service layer and i want get all news from repository and fill into ViewModels and pass to the UI.
my code in service layer is...
public List<NewsViewModel> GetAll()
{
Mapper.CreateMap<News, NewsViewModel>()
.ForMember(dest => dest.Categories, src => src.MapFrom(p => p.Categories))
.ForMember(dest => dest.User, src => src.MapFrom(p => p.User));
Mapper.AssertConfigurationIsValid();
var viewModels = new List<NewsViewModel>();
foreach (var item in _newsRepository.GetAll())
{
var viewModel = Mapper.Map<News, NewsViewModel>(item);
viewModels.Add(viewModel);
}
return viewModels;
}
You don't seem to have created maps for Catagory and User.
Add the following maps:
Mapper.CreateMap<User, UserViewModel>();
Mapper.CreateMap<Category, CategoryViewModel>();
By the way, why are you creating the maps inside the GetAll method? You can create the maps once, usually at application startup.

Deserializing oData to a sane object with ServiceStack

So here's what I'm getting back from the oData service...
{
"odata.metadata":"http://server.ca/Mediasite/Api/v1/$metadata#UserProfiles",
"value":[
{
"odata.id":"http://server.ca/Mediasite/Api/v1/UserProfiles('111111111111111')",
"QuotaPolicy#odata.navigationLinkUrl":"http://server.ca/Mediasite/Api/v1/UserProfiles('111111111111111')/QuotaPolicy",
"#SetQuotaPolicyFromLevel":{
"target":"http://server.ca/Mediasite/Api/v1/UserProfiles('111111111111111')/SetQuotaPolicyFromLevel"
},
"Id":"111111111111111",
"UserName":"testuser",
"DisplayName":"testuser Large",
"Email":"testuser#testuser.ca",
"Activated":true,
"HomeFolderId":"312dcf4890df4b129e248a0c9a57869714",
"ModeratorEmail":"testuser#testuserlarge.ca",
"ModeratorEmailOptOut":false,
"DisablePresentationContentCompleteEmails":false,
"DisablePresentationContentFailedEmails":false,
"DisablePresentationChangeOwnerEmails":false,
"TimeZone":26,
"PresenterFirstName":null,
"PresenterMiddleName":null,
"PresenterLastName":null,
"PresenterEmail":null,
"PresenterPrefix":null,
"PresenterSuffix":null,
"PresenterAdditionalInfo":null,
"PresenterBio":null,
"TrustDirectoryEntry":null
}
]
}
I want to deserialize this into a simple class, like just the important stuff (Id, Username, etc...to the end).
I have my class create, but for the life of me I can't figureout how to throw away all the wrapper objects oData puts around this thing.
Can anyone shed some light?
You can use JsonObject do dynamically traverse the JSON, e.g:
var users = JsonObject.Parse(json).ArrayObjects("value")
.Map(x => new User
{
Id = x.Get<long>("Id"),
UserName = x["UserName"],
DisplayName = x["DisplayName"],
Email = x["Email"],
Activated = x.Get<bool>("Activated"),
});
users.PrintDump();
Or deserialize it into a model that matches the shape of the JSON, e.g:
public class ODataUser
{
public List<User> Value { get; set; }
}
public class User
{
public long Id { get; set; }
public string UserName { get; set; }
public string DisplayName { get; set; }
public string Email { get; set; }
public bool Activated { get; set; }
public string HomeFolderId { get; set; }
public string ModeratorEmail { get; set; }
public bool ModeratorEmailOptOut { get; set; }
public bool DisablePresentationContentCompleteEmails { get; set; }
public bool DisablePresentationContentFailedEmails { get; set; }
public bool DisablePresentationChangeOwnerEmails { get; set; }
public int TimeZone { get; set; }
}
var odata = json.FromJson<ODataUser>();
var user = odata.Value[0];

Resources