How to get param of datatable in controller? - asp.net-mvc

I use databale in view
$("#table-DoctorClosure").DataTable({
"bServerSide": true,
"sAjaxSource": "#Url.Action("PaginationList", "DoctorClosure")",
"fnServerData": function (sSource, aoData, fnCallback) {
aoData.push({ "name": "DoctorId", "value": #ViewBag.doctorId} );
$.ajax({
type: "Get",
data: aoData,
url: sSource,
success: fnCallback
})
},
"aoColumns": [
{ "mData": "Date" },
{ "mData": "Description" },
{
"mData": "Id",
"className": "text-center ",
"render": function(Id, type, full, meta) {
return '<a class="btn-edit btn btn-warning btn-sm m-l-5" href="/Doctor/DoctorClosure/Edit?id=' + Id +'" data-toggle="tooltip" data-placement="top" title="#OperationResource.Edit"><i class="icon-pencil" ></i> </a>' +
'<a class="btn-delete btn btn-sm bg-danger" data-id="'+Id+'" data-toggle="tooltip" data-placement="top" title="#OperationResource.Delete"><i class="icon-trash-o"></i> </a>'
}
},
],
"oLanguage": {
"sUrl": "/Content/styles/datatables/dataTables.persian.txt"
}
});
I want to get DoctorId of aoData
public async Task<ActionResult> PaginationList(DataTableParameter param)
{
???
}
DataTableParameter is
public class DataTableParameter
{
/// <summary>
/// Request sequence number sent by DataTable,
/// same value must be returned in response
/// </summary>
public string sEcho { get; set; }
/// <summary>
/// Text used for filtering
/// </summary>
public string sSearch { get; set; }
/// <summary>
/// Number of records that should be shown in table
/// </summary>
public int iDisplayLength { get; set; }
/// <summary>
/// First record that should be shown(used for paging)
/// </summary>
public int iDisplayStart { get; set; }
/// <summary>
/// Number of columns in table
/// </summary>
public int iColumns { get; set; }
/// <summary>
/// Number of columns that are used in sorting
/// /// </summary>
public int iSortingCols { get; set; }
/// <summary>
/// Comma separated list of column names
/// </summary>
public string sColumns { get; set; }
}

if I understood your question correctly, when you send a data to controller(with ajax or none) you should have a variable in input controller.
you send data and your DoctorId is not in DataTableParameter class. so if you want to get this param you have two solution:
first is add DoctorId in your class(or make view model with this param):
public class DataTableParameter
{
/// <summary>
/// Request sequence number sent by DataTable,
/// same value must be returned in response
/// </summary>
public string sEcho { get; set; }
/// <summary>
/// Text used for filtering
/// </summary>
public string sSearch { get; set; }
/// <summary>
/// Number of records that should be shown in table
/// </summary>
public int iDisplayLength { get; set; }
/// <summary>
/// First record that should be shown(used for paging)
/// </summary>
public int iDisplayStart { get; set; }
/// <summary>
/// Number of columns in table
/// </summary>
public int iColumns { get; set; }
/// <summary>
/// Number of columns that are used in sorting
/// /// </summary>
public int iSortingCols { get; set; }
/// <summary>
/// Comma separated list of column names
/// </summary>
public string sColumns { get; set; }
/// <summary>
/// if you use this you can send and use it in controller
/// </summary>
public int DoctorId { get; set; }
}
the second way is add another param in your controller input:
public async Task<ActionResult> PaginationList(DataTableParameter param, int DoctorId)
{
???
}

Related

Automapper and implementation of Dtos in the service layer

I am creating a Ntier solution which includes Domain Objects, DataAccess Layer,Service layer and the web API layer . I am using AutoMapper to map Dtos and domain objects in the service layer. I would like to know how to write the logic for performing CRUD operations in the service layer. I have written some mapping. Is this the right way of mapping or is there a better way to do it and also please do correct me where I have written the get, save, update, delete operation. I basically need help in implementing my Service layer.
I am getting the following error when I debug the code:
Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.
I get the error at the following line of code in the GetPatient method:
yield return Mapper.Map<PatientDto>(patient);
Domain layer
public class Patient : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public char Gender { get; set; }
public string Phone { get; set; }
}
DataAccess Layer
public class GenericRepository<TEntity> where TEntity : class
{
#region Private member variables...
internal AppointmentBookingContext Context;
internal DbSet<TEntity> DbSet;
#endregion
#region Public Constructor...
/// <summary>
/// Public Constructor,initializes privately declared local variables.
/// </summary>
/// <param name="context"></param>
public GenericRepository(AppointmentBookingContext context)
{
this.Context = context;
this.DbSet = context.Set<TEntity>();
}
#endregion
#region Public member methods...
/// <summary>
/// generic Get method for Entities
/// </summary>
/// <returns></returns>
public virtual IEnumerable<TEntity> Get()
{
IQueryable<TEntity> query = DbSet;
return query.ToList();
}
/// <summary>
/// Generic get method on the basis of id for Entities.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual TEntity GetByID(object id)
{
return DbSet.Find(id);
}
/// <summary>
/// generic Insert method for the entities
/// </summary>
/// <param name="entity"></param>
public virtual void Insert(TEntity entity)
{
DbSet.Add(entity);
}
/// <summary>
/// Generic Delete method for the entities
/// </summary>
/// <param name="id"></param>
public virtual void Delete(object id)
{
TEntity entityToDelete = DbSet.Find(id);
Delete(entityToDelete);
}
/// <summary>
/// Generic Delete method for the entities
/// </summary>
/// <param name="entityToDelete"></param>
public virtual void Delete(TEntity entityToDelete)
{
if (Context.Entry(entityToDelete).State == EntityState.Detached)
{
DbSet.Attach(entityToDelete);
}
DbSet.Remove(entityToDelete);
}
/// <summary>
/// Generic update method for the entities
/// </summary>
/// <param name="entityToUpdate"></param>
public virtual void Update(TEntity entityToUpdate)
{
DbSet.Attach(entityToUpdate);
Context.Entry(entityToUpdate).State = EntityState.Modified;
}
/// <summary>
/// generic method to get many record on the basis of a condition.
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
public virtual IEnumerable<TEntity> GetMany(Func<TEntity, bool> where)
{
return DbSet.Where(where).ToList();
}
/// <summary>
/// generic method to get many record on the basis of a condition but query able.
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
public virtual IQueryable<TEntity> GetManyQueryable(Func<TEntity, bool> where)
{
return DbSet.Where(where).AsQueryable();
}
/// <summary>
/// generic get method , fetches data for the entities on the basis of condition.
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
public TEntity Get(Func<TEntity, Boolean> where)
{
return DbSet.Where(where).FirstOrDefault<TEntity>();
}
/// <summary>
/// generic delete method , deletes data for the entities on the basis of condition.
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
public void Delete(Func<TEntity, Boolean> where)
{
IQueryable<TEntity> objects = DbSet.Where<TEntity>(where).AsQueryable();
foreach (TEntity obj in objects)
DbSet.Remove(obj);
}
/// <summary>
/// generic method to fetch all the records from db
/// </summary>
/// <returns></returns>
public virtual IEnumerable<TEntity> GetAll()
{
return DbSet.ToList();
}
/// <summary>
/// Inclue multiple
/// </summary>
/// <param name="predicate"></param>
/// <param name="include"></param>
/// <returns></returns>
public IQueryable<TEntity> GetWithInclude(
System.Linq.Expressions.Expression<Func<TEntity,
bool>> predicate, params string[] include)
{
IQueryable<TEntity> query = this.DbSet;
query = include.Aggregate(query, (current, inc) => current.Include(inc));
return query.Where(predicate);
}
/// <summary>
/// Generic method to check if entity exists
/// </summary>
/// <param name="primaryKey"></param>
/// <returns></returns>
public bool Exists(object primaryKey)
{
return DbSet.Find(primaryKey) != null;
}
/// <summary>
/// Gets a single record by the specified criteria (usually the unique identifier)
/// </summary>
/// <param name="predicate">Criteria to match on</param>
/// <returns>A single record that matches the specified criteria</returns>
public TEntity GetSingle(Func<TEntity, bool> predicate)
{
return DbSet.Single<TEntity>(predicate);
}
/// <summary>
/// The first record matching the specified criteria
/// </summary>
/// <param name="predicate">Criteria to match on</param>
/// <returns>A single record containing the first record matching the specified criteria</returns>
public TEntity GetFirst(Func<TEntity, bool> predicate)
{
return DbSet.First<TEntity>(predicate);
}
#endregion
}
Service layer
PatientDto.cs
public class PatientDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public char Gender { get; set; }
public string Phone { get; set; }
}
AutoMapperConfiguration.cs
public class AutoMapperConfiguration
{
public static void Configure()
{
Assembly[] assemblies = BuildManager.GetReferencedAssemblies().OfType<Assembly>().ToArray();
Mapper.Initialize(cfg =>
cfg.AddProfiles(AllClasses.FromAssemblies(assemblies)
.Where(
a =>
a.FullName.EndsWith("Mapping")))); }
}
DomainToDtoMapping.cs
public class DomainToDtoMapping : Profile
{
public DomainToDtoMapping()
{
CreateMap<BaseEntity, BaseDto>().ReverseMap();
CreateMap<Patient, PatientDto>().ReverseMap();
}
}
IPatientService
public interface IPatientService
{
IEnumerable<PatientDto> GetPatient();
PatientDto GetPatientById(int id);
int CreatePatient(PatientDto customer);
bool UpdatePatient(PatientDto patient);
bool DeletePatient(int patient);
}
PatientService
public class PatientService : IPatientService
{
private readonly IUnitOfWork _unitOfWork;
public int CreatePatient(PatientDto patientDto)
{
using (var scope = new TransactionScope())
{
var patient = _unitOfWork.PatientRepository.GetByID(patientDto.Id);
_unitOfWork.PatientRepository.Insert(patient);
_unitOfWork.Save();
scope.Complete();
return patient.Id;
}
}
public bool DeletePatient(int id)
{
var success = false;
if (id > 0)
{
using (var scope = new TransactionScope())
{
var patient = _unitOfWork.PatientRepository.GetByID(id);
if (patient != null)
{
_unitOfWork.PatientRepository.Delete(patient);
_unitOfWork.Save();
scope.Complete();
success = true;
}
}
}
return success;
}
public IEnumerable<PatientDto> GetPatient()
{
var patient = _unitOfWork.PatientRepository.GetAll();
if (patient != null)
{
yield return Mapper.Map<PatientDto>(patient);
}
yield return null;
}
public PatientDto GetPatientById(int id)
{
var patient = _unitOfWork.PatientRepository.GetByID(id);
if (patient != null)
{
return Mapper.Map<PatientDto>(patient);
}
return null;
}
public bool UpdatePatient(PatientDto patientDto)
{
var success = false;
if (patientDto != null)
{
using (var scope = new TransactionScope())
{
var patient = _unitOfWork.PatientRepository.GetByID(patientDto.Id);
if (patient != null)
{
_unitOfWork.PatientRepository.Update(patient);
_unitOfWork.Save();
scope.Complete();
success = true;
}
}
}
return success;
}

ASP.NET Identity with dapper and autofac

I am trying to create a new ASP.NET application that uses ASP.NET Identity for authentication combined with autofac and Dapper. I know that I have to combine these 2 projects https://github.com/whisperdancer/AspNet.Identity.Dapper and https://developingsoftware.com/configuring-autofac-to-work-with-the-aspnet-identity-framework-in-mvc-5/
but I don't know how to do it.
Update 1:
I am not going to copy all of the code as it exists on the previous links.
I am using the Repository Pattern like this
public class Repository : DataConnection, IRepository
{
/// <summary>
///
/// </summary>
/// <param name="connection"></param>
public Repository(IDbConnection connection)
: base(connection)
{
}
public IDbConnection GetConnection()
{
return Connection;
}
public IEnumerable<T> Select<T>(Expression<Func<T, bool>> objFunc) where T : new()
{
// Orm Lite Version
return Connection.Select<T>(objFunc);
}
public Dictionary<int, string> Dictionary<K, V>(string cacheKey, string Sql)
{
Dictionary<int, string> items = MemoryCache.Default.Get(cacheKey) as Dictionary<int, string>;
if (items == null || !items.Any())
{
items = Connection.Dictionary<int, string>(Sql);
MemoryCache.Default.Add(cacheKey, items, DateTime.Now.AddMinutes(120));
}
return items;
}
public Dictionary<int, string> Dictionary<K, V>(string Sql)
{
Dictionary<int, string> items;
items = Connection.Dictionary<int, string>(Sql);
return items;
}
public Dictionary<string, string> DictionaryString<K, V>(string Sql)
{
Dictionary<string, string> items;
items = Connection.Dictionary<string, string>(Sql);
return items;
}
public Dictionary<string, string> DictionaryString<K, V>(string cacheKey, string Sql)
{
Dictionary<string, string> items = MemoryCache.Default.Get(cacheKey) as Dictionary<string, string>;
if (items == null || !items.Any())
{
items = Connection.Dictionary<string, string>(Sql);
MemoryCache.Default.Add(cacheKey, items, DateTime.Now.AddMinutes(120));
}
return items;
}
public IList<T> Select<T>(string cacheKey, string Sql, object filter) where T : new()
{
IList<T> items = MemoryCache.Default.Get(cacheKey) as IList<T>;
if (items == null || !items.Any())
{
items = Connection.Select<T>(Sql, filter);
MemoryCache.Default.Add(cacheKey, items, DateTime.Now.AddMinutes(120));
}
return items;
}
//where T : new(); has been omitted here as this function returns int, string etc
public T ExecuteScalar<T>(string Sql, object filter)
{
return Connection.ScalarFmt<T>(Sql, filter);
}
public IList<T> Select<T>(string Sql, object filter)
{
IList<T> items;
items = Connection.Select<T>(Sql, filter);
return items;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public IEnumerable<T> GetAll<T>() where T : new()
{
// Orm Lite Version
return Connection.LoadSelect<T>();
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filters"></param>
/// <returns></returns>
public T GetFirst<T>(string cacheKey, object filters) where T : new()
{
T item = (T)MemoryCache.Default.Get(cacheKey);
if (item == null)
{
item = Connection.SingleById<T>(filters);
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(120));
}
// OrmLite Version
return item;
}
public T GetFirst<T>(object filters) where T : new()
{
T item = Connection.SingleById<T>(filters);
return item;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="instance"></param>
public long Add<T>(T instance) where T : new()
{
//Ormlite Version
//Connection.Save(instance);
var Id = Connection.Insert(instance, selectIdentity: true);
return Id;
}
public void Update<T>(T instance) where T : new()
{
//OrmLite version
Connection.Update(instance);
}
public void Delete<T>(object filters) where T : new()
{
Connection.DeleteById<T>(filters);
}
}
where DataConnection Class is like this
public class DataConnection : IDisposable
{
#region Properties
/// <summary>
///
/// </summary>
private IDbConnection _connection;
/// <summary>
///
/// </summary>
protected IDbConnection Connection
{
get
{
if (_connection.State != ConnectionState.Open && _connection.State != ConnectionState.Connecting)
_connection.Open();
return _connection;
}
}
#endregion
/// <summary>
///
/// </summary>
/// <param name="connection"></param>
public DataConnection(IDbConnection connection)
{
_connection = connection;
}
public DataConnection(string connString)
{
if (connString == "")
connString = ConfigurationManager.ConnectionStrings[0].Name;
_connection = new SqlConnection(connString);
}
/// <summary>
/// Close the connection if this is open
/// </summary>
public void Dispose()
{
if (_connection != null && _connection.State != ConnectionState.Closed)
{
_connection.Close();
//not sure if this line is needed
_connection.Dispose();
}
//the same for the following line
_connection = null;
}
}
The initial configuration of Autofac is being done in 2 places. In a class named IoC like this
public class IoC : ContainerBuilder
{
/// <summary>
///
/// </summary>
private readonly static IoC _instance = new IoC();
/// <summary>
///
/// </summary>
private static object _lock;
/// <summary>
///
/// </summary>
private IContainer _componentsContainer;
/// <summary>
///
/// </summary>
public static IoC Instance
{
get
{
return _instance;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public IContainer GetComponentsContainer()
{
if (_componentsContainer == null)
{
lock (_lock)
{
if (_componentsContainer == null)
_componentsContainer = this.Build();
}
}
return _componentsContainer;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Resolve<T>() where T : class
{
return GetComponentsContainer().Resolve<T>();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ILifetimeScope BeginLifetimeScope()
{
return GetComponentsContainer().BeginLifetimeScope();
}
/// <summary>
///
/// </summary>
private IoC()
{
_lock = new object();
ConfigureDependencies();
}
/// <summary>
///
/// </summary>
private void ConfigureDependencies()
{
//Configure all your depedendencies here!!
//Database connection
var connectionString = ConfigurationManager.ConnectionStrings["DBConnectionStringName"].ConnectionString;
this.Register(c => new SqlConnection(connectionString)).As<IDbConnection>().InstancePerLifetimeScope();
//Database Connection OrmLite
OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
//Repository
this.RegisterType<Repository>().As<IRepository>().InstancePerLifetimeScope();
this.RegisterType<ApplicationUserStore>().As<IUserStore<AppMember,int>>().InstancePerRequest();
this.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
this.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerRequest();
this.Register<IAuthenticationManager>(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerRequest();
}
}
and in ConfigureAuth method of StartUp Class like this
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
//IDataProtectionProvider has to be resolved here as it's the only place where IAppBuilder is available
IoC.Instance.Register<IDataProtectionProvider>(c => app.GetDataProtectionProvider()).InstancePerRequest();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/auth/login")
});
}
}
My ApplicationUserStore Class derives from a custom UserSrore Class like this
public class ApplicationUserStore : UserStore<AppMember>
{
public ApplicationUserStore()
: base()
{
}
}
where UserStore is like this
public class UserStore<TUser> : IUserLoginStore<TUser, int>,
IUserClaimStore<TUser, int>,
IUserRoleStore<TUser, int>,
IUserPasswordStore<TUser, int>,
IUserSecurityStampStore<TUser, int>,
IQueryableUserStore<TUser, int>,
IUserEmailStore<TUser, int>,
IUserPhoneNumberStore<TUser, int>,
IUserTwoFactorStore<TUser, int>,
IUserLockoutStore<TUser, int>,
IUserStore<TUser, int>
where TUser : IdentityMember
{
private UserTable<TUser> userTable;
private RoleTable roleTable;
private UserRolesTable userRolesTable;
// This ASP.NET Identity implemantaion won't use claims
private UserClaimsTable userClaimsTable;
private UserLoginsTable userLoginsTable;
private IRepository Repository;
public IQueryable<TUser> Users
{
get
{
throw new NotImplementedException();
}
}
public UserStore()
{
IRepository repository = IoC.Instance.Resolve<IRepository>();
new UserStore<TUser>(repository);
}
/// <summary>
/// Constructor that takes a dbmanager as argument
/// </summary>
/// <param name="database"></param>
public UserStore(IRepository repository)
{
this.Repository = repository;
userTable = new UserTable<TUser>(repository);
roleTable = new RoleTable(repository);
userRolesTable = new UserRolesTable(repository);
//Claims are not implemented
userClaimsTable = new UserClaimsTable(repository);
userLoginsTable = new UserLoginsTable(repository);
}
There is no reason to write all the methods that the UserStore class has, but it is sure that I make a configuration error in Autofac cause this function
public Task<TUser> FindByNameAsync(string userName)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentException("Null or empty argument: userName");
}
List<TUser> result = userTable.GetUserByName(userName) as List<TUser>;
// Should I throw if > 1 user?
if (result != null && result.Count == 1)
{
return Task.FromResult<TUser>(result[0]);
}
return Task.FromResult<TUser>(null);
}
fails with a null reference error. UserTable is not initialised.
Update 2:
UserTable Class
public class UserTable<TUser>
where TUser : IdentityMember
{
private IRepository Repository;
public UserTable(IRepository repository)
{
this.Repository = repository;
}
And IdentityMember Class is custom as well, as follows
public class IdentityMember : IUser<int>
{
/// <summary>
/// Default constructor
/// </summary>
public IdentityMember()
{
}
/// <summary>
/// Constructor that takes user name as argument
/// </summary>
/// <param name="userName"></param>
public IdentityMember(string userName)
: this()
{
UserName = userName;
}
/// <summary>
/// User ID
/// </summary>
[Alias("id")]
public int Id { get; set; }
/// <summary>
/// User's name
/// </summary>
public string UserName { get; set; }
/// <summary>
/// Email
/// </summary>
public virtual string Email { get; set; }
/// <summary>
/// True if the email is confirmed, default is false
/// </summary>
public virtual bool EmailConfirmed { get; set; }
/// <summary>
/// The salted/hashed form of the user password
/// </summary>
public virtual string PasswordHash { get; set; }
/// <summary>
/// A random value that should change whenever a users credentials have changed (password changed, login removed)
/// </summary>
public virtual string SecurityStamp { get; set; }
/// <summary>
/// PhoneNumber for the user
/// </summary>
public virtual string PhoneNumber { get; set; }
/// <summary>
/// True if the phone number is confirmed, default is false
/// </summary>
public virtual bool PhoneNumberConfirmed { get; set; }
/// <summary>
/// Is two factor enabled for the user
/// </summary>
public virtual bool TwoFactorEnabled { get; set; }
/// <summary>
/// DateTime in UTC when lockout ends, any time in the past is considered not locked out.
/// </summary>
public virtual DateTime? LockoutEndDateUtc { get; set; }
/// <summary>
/// Is lockout enabled for this user
/// </summary>
public virtual bool LockoutEnabled { get; set; }
/// <summary>
/// Used to record failures for the purposes of lockout
/// </summary>
public virtual int AccessFailedCount { get; set; }
}
Any Suggestions?

Entity Framework: Invalid column name

I have problem with this Conference table. The error is :
Invalid column name 'Conference_ConferenceID'
namespace MeetingBoard.Model
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Script.Serialization;
using MeetingBoard.Model.Helpers;
using System.ComponentModel.DataAnnotations.Schema;
/// <summary>
/// A model of the Conference entity. Contains functionality to serialize the entity to JSON as well.
/// </summary>
public class Conference
{
[Key]
public int ConferenceID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int CreatorID { get; set; }
public string Location { get; set; }
public DateTime SubmissionDate { get; set; }
[ForeignKey("CreatorID")]
public virtual User Creator { get; set; }
public int[] RelatedProjectsIDs { get; set; }
public virtual ICollection<ProjectTag> RelatedProjectTags { get; set; }
public DateTime CreatedOn
{
get { return (this.dateCreated == default(DateTime)) ? DateTime.UtcNow : this.dateCreated; }
set { this.dateCreated = value; }
}
private DateTime dateCreated = default(DateTime);
public virtual ICollection<Group> RelatedGroups { get; set; }
public Conference()
{
RelatedGroups = new List<Group>();
}
/// <summary>
/// Generates an object that can be serialized by the JSON serializer of MVC
/// </summary>
/// <param name="happening">An Conference.</param>
/// <returns></returns>
public static Object ToJsonObject(Conference conference)
{
int[] project_ids = conference.RelatedProjectTags.Select<ProjectTag, int>(pt => pt.ProjectID).ToArray();
return new Conference_JSON
{
id = conference.ConferenceID,
title = conference.Title,
Content = conference.Content,
created_timestamp_UTC = Util.DateTimeToMilliTimeStamp(conference.CreatedOn),
SubmissionDate = conference.SubmissionDate,
Location = conference.Location,
creator_avatar = conference.Creator.Avatar,
creator_fullname = conference.Creator.Name,
creator_id = conference.Creator.UserID,
project_ids = project_ids,
};
}
/// <summary>
/// Instantiates a new Conference object based on the json data.
/// </summary>
/// <param name="json_data">The json data needs to have the structure as specified in the private Conference_JSON object.</param>
/// <returns>A new Conference object. The related projects are referenced using an integer array containing project ids.</returns>
public static Conference FromJson(String json_data)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
Conference_JSON conference_object = serializer.Deserialize<Conference_JSON>(json_data);
return FromJsonObject(conference_object);
}
/// <summary>
/// Instantiates a new Conference object based on the private Conference_JSON object.
/// </summary>
/// <param name="json_data">The object needs to be an instance of the private Conference_JSON object.</param>
/// <returns>A new Conference object. The related projects are referenced using an integer array containing project ids.</returns>
public static Conference FromJsonObject(Object conference_object)
{
Conference_JSON conference_json = (Conference_JSON)conference_object;
Conference conference = new Conference
{
ConferenceID = conference_json.id,
Title = conference_json.title,
Content = conference_json.Content,
RelatedProjectsIDs = conference_json.project_ids,
Location = conference_json.Location,
SubmissionDate = conference_json.SubmissionDate,
};
return conference;
}
/// <summary>
/// Defines the structure of the json objects that ar communicated to and from the Frontend.
/// </summary>
private class Conference_JSON
{
/// <summary>
/// The Conference identifier.
/// </summary>
public int id;
public string title;
public string Content;
/// <summary>
/// An numeric representation of the time, in milliseconds from Unix Epoch, UTC timezone.
/// </summary>
public double created_timestamp_UTC;
public string creator_fullname;
public int creator_id;
public string creator_avatar;
/// <summary>
/// Related projects.
/// </summary>
public int[] project_ids;
public string Location;
public DateTime SubmissionDate;
}
}
}
I get this error when there is a mismatch between the code and the DB, in the sense that the code expects to find columns in the DB but they don't exist there. This happens when the DB isn't updated to match the changes in the code. I'd suggest looking at the database that is being hit when you get that error, maybe it's not looking where you expect.

Entity framework assign automaticly new instance entity as deleted

As I'm working on an ASP.NET MVC project I've saw a weird behavior of EF which delays me (to be exact, I'm still stuck on this problem at least month... and only now I've realized that my DDD architecture code is not broken and it's specific an EF-related code bug that I have).
My site has posts. Each post has a set of attributes (PostAttributeValue) and each attribute value has a related PostAttributeDefinition which contains data about it - such as Title, Validation Rules, Raw Value (binary serialized), data type etc.
This is my Post model:
public class Post
{
#region Settings
/// <summary>
/// Maximum linked images
/// </summary>
public static int MaximumLinkedImages
{
get { return Properties.Settings.Default.MaximumPostsLinkedImages; }
}
/// <summary>
/// Maximum linked image size in MB
/// </summary>
public static int MaximumLinkedImageSize
{
get { return Properties.Settings.Default.MaximumPostLinkedImageSize; }
}
/// <summary>
/// Delay hours between posts bumping
/// </summary>
public static int BumpPostDelayHours
{
get { return Properties.Settings.Default.BumpPostDelayHours; }
}
#endregion
#region ctor
public Post()
{
this.Attributes = new List<PostAttributeValue>();
this.LinkedImages = new List<string>();
}
#endregion
/// <summary>
/// The parent category that this post was posted into
/// </summary>
[Required]
public virtual Category ParentCategory { get; set; }
/// <summary>
/// The post unique identifier
/// </summary>
[Key]
public Guid PostIdentifier { get; set; }
/// <summary>
/// The post title (e.g. "Great vila!")
/// </summary>
[Required]
public string Title { get; set; }
/// <summary>
/// The post title url alias (e.g. "great-vila")
/// </summary>
public string TitleUrlAlias { get; set; }
/// <summary>
/// Post extra notes and information written by the author
/// </summary>
[Required]
public string Description { get; set; }
/// <summary>
/// The post item city
/// </summary>
[Required]
public virtual City City { get; set; }
/// <summary>
/// The post item location
/// </summary>
public string Location { get; set; }
/// <summary>
/// Is the post was published and marketed by brokerage (Tivuuch)
/// </summary>
[Required]
public bool Brokerage { get; set; }
/// <summary>
/// Post custom attributes
/// </summary>
public virtual ICollection<PostAttributeValue> Attributes { get; set; }
/// <summary>
/// The post assigned price
/// </summary>
[Required]
public int RequestedPrice { get; set; }
/// <summary>
/// List of images linked with the post (includes only the name of the picture, a.k.a "foo.png", "bar.jpg" etc.)
/// </summary>
public virtual ICollection<string> LinkedImages { get; set; }
public string LinkedImagesSerialized
{
get
{
if (this.LinkedImages == null)
{
this.LinkedImages = new List<string>();
}
return string.Join(",", this.LinkedImages);
}
set
{
if (this.LinkedImages == null)
{
this.LinkedImages = new List<string>();
}
if (string.IsNullOrEmpty(value))
{
return;
}
this.LinkedImages = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
}
/// <summary>
/// Cached generated cached url using IShorterUrlService
/// </summary>
public string GeneratedShorterUrl { get; set; }
/// <summary>
/// Is this post marked as hot
/// </summary>
public bool IsHotPost { get; set; }
/// <summary>
/// The post publish status
/// </summary>
public PostPublishStatus PublishStatus { get; set; }
/// <summary>
/// The post author
/// </summary>
public virtual Account Author { get; set; }
/// <summary>
/// The author IP address (collected to determine different IPs)
/// </summary>
public string AuthorIPAddress { get; set; }
/// <summary>
/// The creation date of the post
/// </summary>
public DateTime CreationDate { get; set; }
/// <summary>
/// The last post modification date
/// </summary>
public DateTime LastUpdatedDate { get; set; }
/// <summary>
/// The date that the post was bumped at, used to sort the posts in category.
/// </summary>
public DateTime LastBumpDate { get; set; }
}
This is PostAttributeValue
public class PostAttributeValue
{
///
/// The attribute value id
///
[Key]
public int AttributeValueId { get; set; }
/// <summary>
/// The value owner post
/// </summary>
public virtual Post OwnerPost { get; set; }
/// <summary>
/// The value attribute definition id
/// </summary>
//public int RelatedAttributeDefinitionId { get; set; }
/// <summary>
/// The value attribute definition
/// </summary>
public virtual PostAttributeDefinition Definition { get; set; }
/// <summary>
/// The stored raw value
/// </summary>
public byte[] RawValue { get; set; }
}
and this is PostAttributeDefinition
public class PostAttributeDefinition
{
///
/// The filter name
///
[Key]
public int DefinitionId { get; set; }
/// <summary>
/// The owner category
/// </summary>
[Required]
public virtual Category OwnerCategory { get; set; }
/// <summary>
/// The filter title
/// </summary>
[Required]
public string Title { get; set; }
/// <summary>
/// Metadata enum that provides extra data about the data type
/// </summary>
public PostAttributeTypeMetadata TypeMetadata { get; set; }
/// <summary>
/// Bitwise metadata that provides data about the object in display mode
/// </summary>
public PostAttributeDisplayModeMetadata DisplayModeMetadata { get; set; }
public PostAttributeEditorType EditorType { get; set; }
/// <summary>
/// The attribute raw default value
/// </summary>
[Required]
public byte[] RawDataValue { get; set; }
/// <summary>
/// The attribute raw associated validation attributes
/// </summary>
public byte[] RawValidationRules { get; set; }
/// <summary>
/// Is this field required
/// </summary>
public bool IsRequired { get; set; }
}
My problem is that when I'm trying to add a new post I'm getting a relationship error (A relationship from the AssociationSet is in the 'Deleted' state)
which is
A relationship from the 'PostAttributeValue_Definition' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'PostAttributeValue_Definition_Source' must also in the 'Deleted' state.
Now, I've saw that the problem is that when I'm assigning to PostAttributeValue a definition, automaticlly it becomes Deleted - even if I'm assigning a definition that I'm fetching from the DB right now.
I've tested the above code:
var db = ServiceLocator.SharedInstance.GetInstance<MyDbContext>();
List<PostAttributeValue> v = new List<PostAttributeValue>();
var entity = db.PostAttributesDefinitions.Where(d => d.DefinitionId==1).Include(d => d.OwnerCategory).First();
v.Add(new PostAttributeValue() { Definition = entity });
Post post = new Post()
{
Title = "foo",
Description = "bar",
City = new City { },
Brokerage = false,
Location = "",
RequestedPrice = 500,
ParentCategory = new Category() { },
AuthorIPAddress = "",
Attributes = v
};
db.Posts.Add(post);
var deletedValuesStore = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)db)
.ObjectContext.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Deleted);
And saw that deletedValuesStore contains 1 item - the definition. When I'm commenting this line there's no items in the store.
Do you got any ideas how it can be solved?
Thanks for your time!
Ok so I figured it out.
Just in case somebody is interest, I've configured my DbContext mistakenly with Required().WithOptional() relationship instead of one to many - Required().WithMany().
Because of that, when I've assigned existing attribute definition, which was already assigned to a value, to a new value - it automatically marked it as deleted.

ASP.NET MVC DropDownListFor with Nested Properties in Model

I have two classes an Entry and Paradigm. The Entry class has a ParadigmId and a Paradigm property. So in my view I have #Model.Entry.Paradigm. How do I build a DropDownListFor using the newer syntax for the Paradigm model?
// Entry Model
[Bind(Exclude = "EntryId")]
public class Entry
{
[ScaffoldColumn(false)]
public int EntryId { get; set; }
.
[Display(Name = "Type")]
public int ParadigmId { get; set; }
public virtual Paradigm Paradigm { get; set; }
}
// Paradigm Model
public class Paradigm
{
[ScaffoldColumn(false)]
public int ParadigmId { get; set; }
[Required]
public string Name { get; set; }
public List<Entry> Entries { get; set; }
}
In my view I have #Html.DropDownListFor(model => model.Entry.ParadigmId, model.Entry.Paradigm). But the model is of type Paradigm not IEnumerable. Since Paradigm is part of my class (for Entity Framework Code First) I do not need to use a separate ViewData/ViewBag that is listed in most examples.
I Googled a bit and saw individuals using Helper/Extension methods to convert a model into a SelectList. What is the best way to use DropDownListFor in my model?
#* Create View *#
<div class="editor-label">
#Html.LabelFor(model => model.Entry.ParadigmId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Entry.ParadigmId, model.Entry.Paradigm)
#Html.ValidationMessageFor(model => model.Entry.ParadigmId)
</div>
Your link Entry.Paradigm lazy loads a single Paradigm, the one referenced by the foreign key. It does not load all the Paradigm's in the database.
If you want to have a dropdown list of all the paradigms, bound to the selected one. Then you will need a separate ViewBag or Model property that contains a list of the them all.
I've been using:
public abstract class DropdownVm
{
/// <summary>
/// Set up a dropdown with the indicated values
/// </summary>
/// <param name="value">the current value, for determining selection</param>
/// <param name="options">list of options to display</param>
/// <param name="prependLabelAndValues">list of alternating label/value entries to insert to the beginning of the list</param>
public List<SelectListItem> SetDropdown<T>(T value, IEnumerable<KeyValuePair<T, string>> options, params object[] prependLabelAndValues)
{
var dropdown = options.Select(o => new SelectListItem { Selected = Equals(o.Key, value), Value = o.Key.ToString(), Text = o.Value }).ToList();
// insert prepend objects
for (int i = 0; i < prependLabelAndValues.Length; i += 2)
{
dropdown.Insert(0, new SelectListItem { Text = prependLabelAndValues[i].ToString(), Value = prependLabelAndValues[i + 1].ToString() });
}
return dropdown;
}
}
/// <summary>
/// ViewModel with a single dropdown representing a "single" value
/// </summary>
/// <typeparam name="T">the represented value type</typeparam>
public class DropdownVm<T> : DropdownVm
{
/// <summary>
/// Flag to set when this instance is a nested property, so you can determine in the view if `!ModelState.IsValid()`
/// </summary>
public virtual bool HasModelErrors { get; set; }
/// <summary>
/// The user input
/// </summary>
public virtual T Input { get; set; }
/// <summary>
/// Dropdown values to select <see cref="Input"/>
/// </summary>
public virtual List<SelectListItem> Dropdown { get; set; }
/// <summary>
/// Set up <see cref="Dropdown"/> with the indicated values
/// </summary>
/// <param name="availableOptions">list of options to display</param>
/// <param name="prependLabelAndValues">list of alternating label/value entries to insert to the beginning of the list</param>
public virtual void SetDropdown(IEnumerable<KeyValuePair<T, string>> availableOptions, params object[] prependLabelAndValues)
{
this.Dropdown = SetDropdown(this.Input, availableOptions, prependLabelAndValues);
}
public override string ToString()
{
return Equals(Input, default(T)) ? string.Empty : Input.ToString();
}
}
Which you create with:
var vm = new DropdownVm<string>();
vm.SetDropdown(new Dictionary<string, string> {
{ "option1", "Label 1" },
{ "option2", "Label 2" },
}, "(Choose a Value)", string.Empty);
or, more specifically in your case:
var models = yourDataProvider.GetParadigms(); // list of Paradigm
var vm = new DropdownVm<int>();
vm.SetDropdown(
models.ToDictionary(m => m.ParadigmId, m => m.Name),
"(Choose a Value)", string.Empty
);
And render in the view with:
<div class="field">
#Html.LabelFor(m => m.Input, "Choose")
#Html.DropDownListFor(m => m.Input, Model.Dropdown)
#Html.ValidationMessageFor(m => m.Input)
</div>

Resources