Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to use PersianCalendar as Table column in entity framework

I have an ASP.NET Web API project in which i'm trying to store my date using Persian calendar. Here is my POCO class.

public class Person
{
    PersianCalendar p = new PersianCalendar();

    public Person()
    {

    }


    public Person(string firstName, string lastName, PersianCalendar birthDate)
    {
        FirstName = firstName;
        LastName = lastName;
        DateOfBirth = birthDate;
    }

    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public PersianCalendar DateOfBirth { get; set; }


}   

I created a POST method for my API.

 public HttpResponseMessage Post([FromBody] Person _p)
    {
        try
        {
            db.Persons.Add(_p);
            db.SaveChanges();
            var msg = Request.CreateResponse(HttpStatusCode.Created,
                _p);
            msg.Headers.Location = new Uri(Request.RequestUri + _p.PersonId.ToString());
            return msg;
        }
        catch(Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
        }
    }  

and i'm send my POST request using Fiddler. enter image description here

but in the Chrome Dev Tools, break point birthDate of my Person class is set to null. enter image description here Can anyone help me with what is wrong? How can i send my date in persian format??

like image 299
AminM Avatar asked Jan 31 '17 07:01

AminM


1 Answers

The DateOfBirth in your model POCO should not be of type PersianCalendar. A calendar is used to manipulate DateTime objects, not as a container of DateTime objects.

Your model should store the date of birth as a normal DateTime, then you can use a PersianCalendar to manipulate it. The easy (but a bit ugly) way to do this is to have a DateTime field and a separate public string property for getting and setting the date as formatted by the Persian calendar:

public class Person
{
    PersianCalendar p = new PersianCalendar();
    public Person()
    {

    }
    public Person(string firstName, string lastName, DateTime birthDate)
    {
        FirstName = firstName;
        LastName = lastName;
        DateOfBirth = birthDate;
    }
    public Person(string firstName, string lastName, string birthDateString)
    {
        FirstName = firstName;
        LastName = lastName;
        DateOfBirthString = birthDateString;
    }

    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public DateTime DateOfBirth;
    public string DateOfBirthString
    {
        get
        {
            return string.Format("{0}/{1}/{2}", p.GetYear(DateOfBirth), p.GetMonth(DateOfBirth), p.GetDayOfMonth(DateOfBirth));
        }
        set
        {
            var parts = value.Split('/');
            DateOfBirth = p.ToDateTime(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), 0, 0, 0, 0);
        }
    }
}

Keep in mind that a DateTime represents a general specific moment in time. It does not have any uniquely correct string representation. But if you use something like what I have above, then you are kind of deciding that for your application the only correct string representation is a Persian date, formatted as yyyy/MM/dd.


EDIT: You can also create a custom JSON JsonConverter and use that in your model. Your POCO model could then look like this:

public class Person
{
    public Person() { }
    public Person(string firstName, string lastName, DateTime birthDate)
    {
        FirstName = firstName;
        LastName = lastName;
        DateOfBirth = birthDate;
    }
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [JsonConverter(typeof(PersianDateConverter))]
    public DateTime DateOfBirth;
}

And the PersianDateConverter class looks like this:

public class PersianDateConverter : JsonConverter
{
    PersianCalendar pc = new PersianCalendar();
    public PersianDateConverter()
    {

    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string persianDateString = reader.Value as string;
        if (persianDateString == null)
            throw new ArgumentException("Error in PersionDateConverter.ReadJson: Got null string");

        var parts = persianDateString.Split('/');
        return pc.ToDateTime(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), 0, 0, 0, 0);
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        DateTime d = (DateTime)value;
        string output = string.Format("{0}/{1}/{2}", pc.GetYear(d), pc.GetMonth(d), pc.GetDayOfMonth(d));
        writer.WriteValue(output);
    }
    public override bool CanConvert(Type objectType)
    {
        if (objectType.Name == "DateTime")
            return true;
        return false;
    }
}

Note: This PersianDateConverter is not well tested for edge cases. Seems to work ok as long as the data it is manipulating is valid though.

like image 116
user1429080 Avatar answered Nov 05 '22 07:11

user1429080