I try to make a treeview with jsTree plugin.
So In viewmodel I have a function GetTreeViewList- which returns a ViewModel. It should get the first parent node 0 and then it calls GetChildNodes() function - which should take Child Nodes.
But when I try to create the rootNode of type CategoryViewModel() - it gives me an exception that the object is no set to an instance of an object
public class CategoryViewModel
{
public List<CategoryLanguages> lstCategories { get; set; }
private readonly ICategoriesLanguagesRepository catRepository;
public CategoryViewModel() : this(new CategoryLanguageRepository())
{
}
public CategoryViewModel(ICategoriesLanguagesRepository catRepository)
{
this.catRepository = catRepository;
}
public string EmployeeCode { get; set; }
public string EmployeeName { get; set; }
public IList<CategoryViewModel> ChildNodes { get; set; }
public CategoryViewModel GetTreeVeiwList()
{
CategoryLanguages parrentNodes = catRepository.GetAllParrentCaregories();
CategoryViewModel rootNode = new CategoryViewModel()
{
EmployeeCode = parrentNodes.CategoryLanguagesID.ToString(),
EmployeeName = parrentNodes.Title
};
GetChildNode(rootNode, parrentNodes);
return rootNode;
}
private void GetChildNode(CategoryViewModel rootNode,CategoryLanguages item)
{
if (rootNode != null)
{
List<CategoryLanguages> childNodes= catRepository.GetChildNodes(item);
if (childNodes.Count > 0)
{
foreach (var childRootNode in childNodes)
{
CategoryViewModel chdnode = new CategoryViewModel { EmployeeCode = childRootNode.CategoryLanguagesID.ToString(), EmployeeName = childRootNode.Title };
GetChildNode(chdnode, childRootNode);
rootNode.ChildNodes.Add(chdnode);
}
}
}
Here is my Controller
public class CategoryController : Controller
{
public ActionResult Index()
{
CategoryViewModel ob = new CategoryViewModel();
ob.GetTreeVeiwList();
return View(ob);
}
}
Related
Fetch data from database some error occur here (AdminPurpose con = i.a ) Message show Cannot implicitly converted type.Please see below for my code snippets:
public JsonResult GetInfor()
{
List<AdminPurpose> all = new List<AdminPurpose>();;
using (db_Hajj_UmrahEntities dc= new db_Hajj_UmrahEntities()) {
var datas = (from a in dc.Duas join b in dc.Purposes on a.PurposeId equals b.Id
select new {
a,
b.PurPose1
});
if(datas != null) {
foreach (var i in datas)
{
AdminPurpose con = i.a ;
con.PurPose1 = i.PurPose1;
all.Add(con);
}
}
}
return new JsonResult { Data = all, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
Model class one to many relation here it's using
[MetadataType(typeof(DuaMetaData))]
public partial class AdminPurpose
{
public string PurPose1 { get; set; }
}
public class DuaMetaData
{
public string Dua_Name { get; set; }
public string Arabic_Word { get; set; }
public string Translation_English { get; set; }
public string Source { get; set; }
[Display(Name = "Purpose")]
public int PurposeId { get; set; }
}
When I try update database the property Childrens not saving but SortOrder
and display name are success.
This is my model:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int64 Id { get; set; }
public Int64? LanguageId { get; set; }
[ForeignKey("LanguageId")]
public Language Language { get; set; }
public int SortOrder { get; set; }
public string DisplayName { get; set; }
[ForeignKey("Childrens")]
public Int64? ParentId { get; set; }
public ICollection<Menu> Childrens { get; set; }
I called this function with new parameters:
public void SaveMenu(List<Menu> newMenu)
{
foreach(Menu _addMenu in newMenu)
{
this.Update(_addMenu);
}
this.Commit();
}
public void Update(T entity)
{
try
{
DbEntityEntry _dbEntityEntry = this.DbContext.Entry(entity);
DbContext.Entry(entity).State = EntityState.Modified;
if (_dbEntityEntry.State == EntityState.Detached)
this.dbSet.Attach(entity);
_dbEntityEntry.State = EntityState.Modified;
}
}
public bool Commit()
{
try
{
this.DbContext.SaveChanges();
}
catch (Exception ex)
{
return false;
}
return true;
}
And the childrens are not change but sortOrder success to change.
Why is it happening?
EDIT:
I found solution the problem because the children objects are dummy and need to get the "real" object from the DB
public void SaveMenu(List<Menu> newMenu)
{
foreach(Menu _addMenu in newMenu)
{
List<Menu> listMenu = new List<Menu>();
foreach (Menu child in _addMenu.Childrens)
{
Menu _menuFromDB = this.Query().FirstOrDefault(s => s.Id == child.Id);
_menuFromDB.SortOrder = child.SortOrder;
listMenu.Add(_menuFromDB);
}
_addMenu.Childrens = listMenu;
this.Update(_addMenu,null);
}
this.Commit();
}
I have a public property which is an object that contains numerous properties itself. Using ASP.net MVC, when I serialize the JSON data I simply add the [JsonIgnore] attribute wherever I use the object so it doesn't display the contents.
Is there a way to add the [JsonIgnore] attribute to the class so it never is serialized?
//[JsonIgnore] ??
public class DataObj
{
public string ConnectionName { get; set; }
public string Query { get; set; }
...
}
public class Customer
{
public string First { get; set; }
public string Last { get; set; }
[JsonIgnore]
public DataObj Foo { get; set; }
}
public class ShipAddress
{
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
[JsonIgnore]
public DataObj Foo { get; set; }
}
My solution after receiving the code provided by jvanrhyn.
Also, here is a link that explains more.
public class DataObjFilterContractResolver : DefaultContractResolver
{
public static readonly DataObjFilterContractResolver Instance = new DataObjFilterContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member,MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.DeclaringType.Name.StartsWith("DataObj") || property.PropertyName == "DataObj")
{
property.ShouldSerialize = instance => false;
}
return property;
}
}
public class UtcJsonResult : JsonResult
{
public UtcJsonResult(object data)
{
Data = data;
JsonRequestBehavior = JsonRequestBehavior.AllowGet;
}
private const string DateFormat = #"yyyy-MM-dd HH:mm:ssZ";
public override void ExecuteResult(ControllerContext context)
{
if (context == null) throw new ArgumentNullException("context");
if (Data == null) return;
var response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
if (ContentEncoding != null) response.ContentEncoding = ContentEncoding;
var isoConvert = new IsoDateTimeConverter {DateTimeFormat = DateFormat};
JsonConvert.DefaultSettings =
() => new JsonSerializerSettings
{ ContractResolver = new DataObjFilterContractResolver()}; //<--- Used here
var json = JsonConvert.SerializeObject(Data, isoConvert);
response.Write(json);
}
}
You can add a Contract Resolver in your project.
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public new static readonly ShouldSerializeContractResolver Instance =
new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member,
MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.DeclaringType == typeof(DataObj))
{
property.ShouldSerialize =
instance =>
{
return false;
};
}
return property;
}
}
I'm working on a web site that can manipulate some categories and subcategories
my model for each of the is :
public class Category
{
[Key]
public int Categoryid { get; set; }
[Required , StringLength(50)]
public string Categoryname { get; set; }
public virtual List<SubCategory> SubCategories { get; set; }
public static string Serialize(Category cat)
{
string jObject= JsonConvert.SerializeObject(cat);
return jObject;
}
public static Category DeSerialize(string cat)
{
Category Dcat = JsonConvert.DeserializeObject<Category>(cat);
return Dcat;
}
}
--
public class SubCategory
{
[Key]
public int SubCategoryid { get; set; }
[Required, StringLength(50)]
public string SubCategoryname { get; set; }
public int Categoryid { get; set; }
public SubCategory( string name)
{
SubCategoryname = name;
}
public SubCategory()
{
}
}
And my Action that edit/create the subcategories and Categories t is :
[HttpPost]
public ActionResult Edit(int id, string txtSub, string subCreate, string saveAll)
{
Category Cat = context.Categories.Single(cat => cat.Categoryid == id);
UpdateModel(Cat, new string[] { "Categoryname "});
if (ModelState.IsValid)
{
// Create Sub
if (subCreate!= null)
{
if (txtSub != "")
{
context.SubCategories.Add(new SubCategory(txtSub) { Categoryid = Cat.Categoryid });
context.SaveChanges();
}
return RedirectToAction("Edit");
}
if (saveAll!= null)
{
// Edit Sub/Cat
for (int i = 0; i < Cat.SubCategories.Count; i++)
{
context.Entry(Cat.SubCategories[i]).State = EntityState.Modified;
}
context.Entry(Cat).State = EntityState.Modified;
context.SaveChanges();
return RedirectToAction("index");
}
}
return View();
}
so the Problem is I cant update specifically the name of my SubCategories because it a nested List of
custom object ....
I read I could specify the logic in the modelupdate() but i just cant do it .
I tried to add
this model updater :
UpdateModel(Cat.SubCategories, new string[] { "SubCategories.SubCategoryname" });
this model updater :
for(int i = 0;iCat.SubCategories.Count;i++)
{
UpdateModel(Cat.SubCategories[0], new string[] { "SubCategories.SubCategoryname" });
}
this model updater :
for(int i = 0;iCat.SubCategories.Count;i++)
{
UpdateModel(Cat.SubCategories[0], new string[] { "SubCategories.SubCategoryname" });
}
this model updater :
for(int i = 0;iCat.SubCategories.Count;i++)
{
UpdateModel(Cat.SubCategories[0], new string[] { "SubCategories["+i+"].SubCategoryname" });
}
I know it possible cause when I'm only doing updateModel(Cat) everyting is greatly binded and work
.But for a security reason I want to only doint it on name of the model, not on ids .
all of them didn't work . so im shure im just missing up a little mistake! Thanks
for your TIME!
I have tried many different ways and looked at different posts, but still haven't come across a solution for this way of auditing. Below is my DBContext template file. I customised it by adding the OnContextCreated() partial method and assign the SavingChanges event to my OnSavingChanges event handler.
namespace ARSystem.Models
{
public partial class ARSEntities : ObjectContext
{
public ARSEntities()
: base("name=ARSEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public string UserName { get; set; }
List<DBAudit> auditTrailList = new List<DBAudit>();
public enum AuditActions
{
I,
U,
D
}
partial void OnContextCreated()
{
this.SavingChanges += new EventHandler(OnSavingChanges);
}
public void OnSavingChanges(object sender, EventArgs e)
{
IEnumerable<ObjectStateEntry> changes = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);
foreach (ObjectStateEntry stateEntryEntity in changes)
{
if (!stateEntryEntity.IsRelationship &&
stateEntryEntity.Entity != null &&
!(stateEntryEntity.Entity is DBAudit))
{//is a normal entry, not a relationship
DBAudit audit = this.AuditTrailFactory(stateEntryEntity, UserName);
auditTrailList.Add(audit);
}
}
if (auditTrailList.Count > 0)
{
foreach (var audit in auditTrailList)
{//add all audits
this.AddToDBAudit(audit);
}
}
}
private DBAudit AuditTrailFactory(ObjectStateEntry entry, string UserName)
{
DBAudit audit = new DBAudit();
audit.AuditId = Guid.NewGuid().ToString();
audit.RevisionStamp = DateTime.Now;
audit.TableName = entry.EntitySet.Name;
audit.UserName = UserName;
if (entry.State == EntityState.Added)
{//entry is Added
audit.NewData = GetEntryValueInString(entry, false);
audit.Actions = AuditActions.I.ToString();
}
else if (entry.State == EntityState.Deleted)
{//entry in deleted
audit.OldData = GetEntryValueInString(entry, true);
audit.Actions = AuditActions.D.ToString();
}
else
{//entry is modified
audit.OldData = GetEntryValueInString(entry, true);
audit.NewData = GetEntryValueInString(entry, false);
audit.Actions = AuditActions.U.ToString();
IEnumerable<string> modifiedProperties = entry.GetModifiedProperties();
//assing collection of mismatched Columns name as serialized string
audit.ChangedColumns = XMLSerializationHelper.XmlSerialize(modifiedProperties.ToArray());
}
return audit;
}
private string GetEntryValueInString(ObjectStateEntry entry, bool isOrginal)
{
if (entry.Entity is EntityObject)
{
object target = CloneEntity((EntityObject)entry.Entity);
foreach (string propName in entry.GetModifiedProperties())
{
object setterValue = null;
if (isOrginal)
{
//Get orginal value
setterValue = entry.OriginalValues[propName];
}
else
{
//Get orginal value
setterValue = entry.CurrentValues[propName];
}
//Find property to update
PropertyInfo propInfo = target.GetType().GetProperty(propName);
//update property with orgibal value
if (setterValue == DBNull.Value)
{//
setterValue = null;
}
propInfo.SetValue(target, setterValue, null);
}//end foreach
XmlSerializer formatter = new XmlSerializer(target.GetType());
XDocument document = new XDocument();
using (XmlWriter xmlWriter = document.CreateWriter())
{
formatter.Serialize(xmlWriter, target);
}
return document.Root.ToString();
}
return null;
}
public EntityObject CloneEntity(EntityObject obj)
{
DataContractSerializer dcSer = new DataContractSerializer(obj.GetType());
MemoryStream memoryStream = new MemoryStream();
dcSer.WriteObject(memoryStream, obj);
memoryStream.Position = 0;
EntityObject newObject = (EntityObject)dcSer.ReadObject(memoryStream);
return newObject;
}
public DbSet<Student> Students { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<aspnet_Applications> aspnet_Applications { get; set; }
public DbSet<aspnet_Membership> aspnet_Membership { get; set; }
public DbSet<aspnet_Roles> aspnet_Roles { get; set; }
public DbSet<aspnet_SchemaVersions> aspnet_SchemaVersions { get; set; }
public DbSet<aspnet_Users> aspnet_Users { get; set; }
public DbSet<vw_aspnet_Applications> vw_aspnet_Applications { get; set; }
public DbSet<vw_aspnet_MembershipUsers> vw_aspnet_MembershipUsers { get; set; }
public DbSet<vw_aspnet_Roles> vw_aspnet_Roles { get; set; }
public DbSet<vw_aspnet_Users> vw_aspnet_Users { get; set; }
public DbSet<vw_aspnet_UsersInRoles> vw_aspnet_UsersInRoles { get; set; }
public DbSet<Cours> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Modules> Modules { get; set; }
public DbSet<EnrollmentsByCourse> EnrollmentsByCourse { get; set; }
public DbSet<EnrollmentsByCourseAudit> EnrollmentsByCourseAudit { get; set; }
public DbSet<DBAudit> DBAudit { get; set; }
}
}
However, when I compile, i get the error message that:
Error 1 'ARSystem.Models.ARSEntities.OnModelCreating(System.Data.Entity.DbModelBuilder)': no suitable method found to override C:\Users\mngum\Documents\Visual Studio 2010\Projects\ARSystem\ARSystem\Models\ARSystem.Context.cs 35 33 ARSystem
I cannot see the OnContextCreated method in the DBContext metadata class but i can find it in the edmx designer. Please let me know how i can implement the OnContextCreated() method such that I can override the SavingChanges event for auditing purposes.
DbContext does not have an OnContextCreated event but that's not a problem because you don't need it to achieve the same. Instead with DbContext the SaveChanges method is overridable. So instead of your OnSavingChanges event handler you use:
public override int SaveChanges()
{
// custom code...
return base.SaveChanges();
}
This method will be called whenever you call ARSEntities.SaveChanges() and you can perform custom actions before you call the base.SaveChanges() of the base DbContext (ARSEntities must be derived from DbContext of course.)
You also can access the underlying ObjectContext from the DbContext:
public override int SaveChanges()
{
var objectContext = ((IObjectContextAdapter)this).ObjectContext;
// use methods and properties of ObjectContext now like
// objectContext.ObjectStateManager, etc.
// custom code...
return base.SaveChanges();
}
Here was a similar question and answer about change auditing with EF 4.1/DbContext:
Entity Framework 4.1 DbContext Override SaveChanges to Audit Property Change