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;
}
}
Related
Summary:
I want a data annotation validator to reference another property in the same class (TitleAuthorAndPublishingConfiguration).
However, DB.SaveChanges() is not being called on this class directly. Rather it is being called on the parent of this class (WebsiteConfiguration).
Therefore validationContext.ObjectType is returning WebsiteConfiguration and I am unable to refer to properties of TitleAuthorAndPublishingConfiguration within the data annotation validator.
WebsiteConfiguration.cs
public class WebsiteConfiguration
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing { get; set; }
public BookChaptersAndSectionsConfiguration BookChaptersAndSections { get; set; }
public SocialMediaLoginsConfiguration SocialMediaLogins { get; set; }
public TagGroupsConfiguration TagGroups { get; set; }
}
public class TitleAuthorAndPublishingConfiguration
{
public string BookTitle { get; set; }
public bool IsPublished { get; set; }
// how do I access a property of current model when calling DB.SaveChanges() on parent?
[RequiredIfOtherFieldIsEnabled("IsPublished")]
public string Publisher { get; set; }
}
// ... and other sub models...
ApplicationDbContext.cs
DbSet<WebsiteConfiguration> WebsiteConfiguration {get;set;}
Example Update Code
public void SeedWebsiteConfiguration()
{
var titleAuthorAndPublishingConfiguration = new TitleAuthorAndPublishingConfiguration()
{
// seed values
};
var bookChaptersAndSectionsConfiguration = new BookChaptersAndSectionsConfiguration()
{
// seed values
};
var socialMediaLoginConfiguration = new SocialMediaLoginsConfiguration()
{
// seed values
};
var tagGroupsConfiguration = new TagGroupsConfiguration()
{
// seed values
};
var websiteConfiguration = new WebsiteConfiguration()
{
TitleAuthorAndPublishing = titleAuthorAndPublishingConfiguration,
BookChaptersAndSections = bookChaptersAndSectionsConfiguration,
SocialMediaLogins = socialMediaLoginConfiguration,
TagGroups = tagGroupsConfiguration
};
DB.WebsiteConfiguration.Add(websiteConfiguration);
DB.SaveChanges();
}
Validator Code
public class RequiredIfOtherFieldIsEnabledAttribute : ValidationAttribute
{
private string _ifWhatIsEnabled { get; set; }
public RequiredIfOtherFieldIsEnabledAttribute(string IfWhatIsEnabled)
{
_ifWhatIsEnabled = IfWhatIsEnabled;
}
protected override ValidationResult IsValid(object currentPropertyValue, ValidationContext validationContext)
{
var isEnabledProperty = validationContext.ObjectType.GetProperty(_ifWhatIsEnabled);
if (isEnabledProperty == null)
{
return new ValidationResult(
string.Format("Unknown property: {0}", _ifWhatIsEnabled)
);
}
var isEnabledPropertyValue = (bool)isEnabledProperty.GetValue(validationContext.ObjectInstance, null);
if (isEnabledPropertyValue == true)
{
if (String.IsNullOrEmpty(currentPropertyValue.ToString()))
{
return new ValidationResult(String.Format("This field is required if {0} is enabled", isEnabledProperty));
}
}
return ValidationResult.Success;
}
}
Questions
Is there a way for me to access child model properties from validationContext?
Am I misguided in my approach? Is there a better way to store multiple models as part of a larger model in a single DB table?
I was hoping not to have multiple config tables and calls to the DB. (There are 4 child models in this example, but there may be 10+ in the next app.)
The setup above meets my needs in so many ways. But I don't want to give up the functionality of DataAnnotations on the sub models!
Bonus Question
I have come across a few posts like this one:
How can I tell the Data Annotations validator to also validate complex child properties?
But that is 4 years old, and I'm wondering if anything has changed since then.
Am I trying to do something that is basically impossible (or at least very difficult)?
Am I trying to do something that is basically impossible (or at least
very difficult)?
No, there is a very simple solution that integrates perfectly with the framework and technologies using DataAnnotations.
You can create a custom ValidationAttribute that is called by EF Validation and call Validator.TryValidateObject inside. This way, when CustomValidation.IsValid is called by EF you launch child complex object validation by hand and so on for the whole object graph. As a bonus, you can gather all errors thanks to CompositeValidationResult.
i.e.
using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
public class Program
{
public static void Main() {
var person = new Person {
Address = new Address {
City = "SmallVille",
State = "TX",
Zip = new ZipCode()
},
Name = "Kent"
};
var context = new ValidationContext(person, null, null);
var results = new List<ValidationResult>();
Validator.TryValidateObject(person, context, results, true);
PrintResults(results, 0);
Console.ReadKey();
}
private static void PrintResults(IEnumerable<ValidationResult> results, Int32 indentationLevel) {
foreach (var validationResult in results) {
Console.WriteLine(validationResult.ErrorMessage);
Console.WriteLine();
if (validationResult is CompositeValidationResult) {
PrintResults(((CompositeValidationResult)validationResult).Results, indentationLevel + 1);
}
}
}
}
public class ValidateObjectAttribute: ValidationAttribute {
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
var results = new List<ValidationResult>();
var context = new ValidationContext(value, null, null);
Validator.TryValidateObject(value, context, results, true);
if (results.Count != 0) {
var compositeResults = new CompositeValidationResult(String.Format("Validation for {0} failed!", validationContext.DisplayName));
results.ForEach(compositeResults.AddResult);
return compositeResults;
}
return ValidationResult.Success;
}
}
public class CompositeValidationResult: ValidationResult {
private readonly List<ValidationResult> _results = new List<ValidationResult>();
public IEnumerable<ValidationResult> Results {
get {
return _results;
}
}
public CompositeValidationResult(string errorMessage) : base(errorMessage) {}
public CompositeValidationResult(string errorMessage, IEnumerable<string> memberNames) : base(errorMessage, memberNames) {}
protected CompositeValidationResult(ValidationResult validationResult) : base(validationResult) {}
public void AddResult(ValidationResult validationResult) {
_results.Add(validationResult);
}
}
public class Person {
[Required]
public String Name { get; set; }
[Required, ValidateObject]
public Address Address { get; set; }
}
public class Address {
[Required]
public String Street1 { get; set; }
public String Street2 { get; set; }
[Required]
public String City { get; set; }
[Required]
public String State { get; set; }
[Required, ValidateObject]
public ZipCode Zip { get; set; }
}
public class ZipCode {
[Required]
public String PrimaryCode { get; set; }
public String SubCode { get; set; }
}
After changing relationship of Question and PossibleAnswer from Many-to-many to One-to-many I got an exception: "The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: Multiplicity constraint violated. The role 'PossibleAnswer_Question_Source' of the relationship 'WebUI.Models.PossibleAnswer_Question' has multiplicity 1 or 0..1." What does it mean?
Here is my model:
public class Question
{
public int ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
public virtual ICollection<PossibleAnswer> PossibleAnswers { get; set; }
public virtual ICollection<Results> Results { get; set; }
}
public class PossibleAnswer
{
public int ID { get; set; }
public string Text { get; set; }
public virtual Question Question { get; set; }
}
And view model for Question (I know that ToQuestion should be in controller, I will rearrange it later):
public class QuestionVM
{
public QuestionVM() {
}
public QuestionVM(Question question) : this()
{
ID = question.ID;
Text = question.Text;
IsAssociatedWithProfessor = question.IsAssociatedWithProfessor;
IsAssociatedWithAssistant = question.IsAssociatedWithAssistant;
}
public int? ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
private IEnumerable<string> _possibleAnswers;
public IEnumerable<string> PossibleAnswers
{
get
{
return _possibleAnswers ?? new List<string>(){"", "", "", "", ""};
}
set
{
_possibleAnswers = value;
}
}
public Question ToQuestion()
{
Question question = new Question
{
Text = this.Text,
IsAssociatedWithProfessor = this.IsAssociatedWithProfessor,
IsAssociatedWithAssistant = this.IsAssociatedWithAssistant,
PossibleAnswers = new List<PossibleAnswer>()
};
//ID will be null if creating new question
if(ID != null)
{
question.ID = (int) ID;
}
foreach (string possibleAnswer in this.PossibleAnswers)
{
if (!String.IsNullOrEmpty(possibleAnswer))
{
question.PossibleAnswers.Add(new PossibleAnswer { Text = possibleAnswer });
}
}
return question;
}
}
Here is my post method for creating new question:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddQuestion(QuestionVM questionVM)
{
try
{
if (ModelState.IsValid)
{
Question question = questionVM.ToQuestion();
context.Questions.Add(question);
context.SaveChanges();
return RedirectToAction("Questions");
}
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Trenutno nije moguće snimiti promjene, pokušajte ponovo.");
}
return View(questionVM);
}
Line:question.PossibleAnswers.Add(new PossibleAnswer { Text = possibleAnswer });
causes the exception since I didn't save possible answers in database before I am adding them to question... But how can I add them to database without use of DbContext (since it is not a good practice to use DbContext in method which converts view model to model)?
Error is coming because PossibleAnswers are not being marked as added entity.
So update your QuestionVM like below:
public class QuestionVM
{
public QuestionVM() {
}
public QuestionVM(Question question) : this()
{
ID = question.ID;
Text = question.Text;
IsAssociatedWithProfessor = question.IsAssociatedWithProfessor;
IsAssociatedWithAssistant = question.IsAssociatedWithAssistant;
}
public int? ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
private IEnumerable<string> _possibleAnswers;
public IEnumerable<string> PossibleAnswers
{
get
{
return _possibleAnswers ?? new List<string>(){"", "", "", "", ""};
}
set
{
_possibleAnswers = value;
}
}
public Question ToQuestion()
{
Question question = new Question
{
Text = this.Text,
IsAssociatedWithProfessor = this.IsAssociatedWithProfessor,
IsAssociatedWithAssistant = this.IsAssociatedWithAssistant,
PossibleAnswers = new List<PossibleAnswer>()
};
//ID will be null if creating new question
if(ID != null)
{
question.ID = (int) ID;
}
return question;
}
public List<PossibleAnswer> GetPosibleAnswers()
{
var listOfPossibleAnswers = new List<PossibleAnswer>();
foreach (string possibleAnswer in this.PossibleAnswers)
{
if (!String.IsNullOrEmpty(possibleAnswer))
{
listOfPossibleAnswers.Add(new PossibleAnswer { Text = possibleAnswer });
}
}
return listOfPossibleAnswers;
}
}
and then update your code like below.
if (ModelState.IsValid)
{
Question question = questionVM.ToQuestion();
context.Questions.Add(question);
context.SaveChanges();
question.PossibleAnswers.AddRange(questionVM.GetPosibleAnswers());
context.SaveChanges();
return RedirectToAction("Questions");
}
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);
}
}
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
I'm using LINQ-to-SQL for CRUD functionality, and DataContractJsonSerializer to serialize the object to JSON. I am also using ASP.NET MVC's data binding to post values to an MVC action that does the inserting. The problem is that it will serialize all of the properties except the Id property. I've got the model set up as so:
[Serializable]
[DataContract(Name = "campaign")]
[Table(Name = "hl.campaigns")]
public class Campaign
{
[DataMember(Name = "id")]
[Column(Name = "id", AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]
public Int32 Id { get; set; }
[DataMember(Name = "createdBy")]
[Column(Name = "created_by")]
public Int32 CreatedBy { get; set; }
[DataMember(Name = "createdOnUtc")]
[Column(Name = "created_on_utc")]
public DateTime CreatedOnUtc { get; set; }
[DataMember(Name = "name")]
[Column(Name = "name", DbType = "NVarChar(256)")]
public String Name { get; set; }
/* more properties here */
}
Here is my custom JsonDataContractActionResult:
public class JsonDataContractActionResult : ActionResult
{
public JsonDataContractActionResult(Object data)
{
this.Data = data;
}
public Object Data { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
var serializer = new DataContractJsonSerializer(this.Data.GetType());
String output = String.Empty;
using (var ms = new MemoryStream())
{
serializer.WriteObject(ms, this.Data);
output = Encoding.Default.GetString(ms.ToArray());
}
context.HttpContext.Response.ContentType = "application/json";
context.HttpContext.Response.Write(output);
}
}
Here's the action (JsonContract() returns a JsonDataContractActionResult):
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Modify([Bind(Prefix = "campaign")] Campaign campaign)
{
if (campaign.Id == 0)
{
try
{
CoreDB.Campaigns.InsertOnSubmit(campaign);
CoreDB.SubmitChanges();
return JsonContract(campaign);
}
catch(Exception ex)
{
// TODO: error handling
}
}
return null; // TODO: modification
}
The only thing I can think of is that somehow data binding is preventing the Id property from being serialized because it was populated after it was deserialized from the form data. Any suggestions?
What does the regular Json() method return for this object?
According to this post... there might be an issue with the automatic backing fields in C#:
http://aaron-powell.spaces.live.com/blog/cns!91A824220E2BF369!150.entry