0

Without serializing getting data from API response

var apiResponseDetails = authorityApiResponse.Content.ReadAsStringAsync().Result;
"[
    {
        \"<RoleName>k__BackingField\":\"L5 _Admin _Role\",
        \"<RoleType>k__BackingField\":\"565,1\"
    }
]"

While Deserializing the same response getting null for RoleName and RoleType

lstRole = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ChangeRoleNotification>>(Convert.ToString(apiResponseDetails));
Name                Value                               
lstRole             Count = 1                           
    [0]             {Presentation.Common.ChangeRoleNotification}    
       RoleName     null                                            
       RoleType     null

[Serializable]
public class ChangeRoleNotification
{
    [Newtonsoft.Json.JsonProperty(PropertyName = "RoleName")]
    public string RoleName { get; set; }
    [Newtonsoft.Json.JsonProperty(PropertyName = "RoleType")]
    public string RoleType { get; set; }
}
...

GetUserRolesDetailsRequest getUserRolesDetails = new GetUserRolesDetailsRequest();
getUserRolesDetails.UserID = objUser.UserId;
getUserRolesDetails.RoleName = HttpContext.Current.Session["UserTypeName"].ToString();
getUserRolesDetails.RoleType = HttpContext.Current.Session["RoleType"].ToString();
getUserRolesDetails.RoleID = Convert.ToInt64(HttpContext.Current.Session["RoleID"]);
    
System.Net.Http.HttpResponseMessage authorityApiResponse = new System.Net.Http.HttpResponseMessage(false ? HttpStatusCode.OK : HttpStatusCode.BadRequest);
System.Net.Http.HttpContent RequestDetails = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(getUserRolesDetails), Encoding.UTF8);

if (!String.IsNullOrEmpty(GetWebConfigKeyValueStatic("FrameworkApiURL")))
{
    authorityApiResponse = API.PostAPIAsJson($"{GetWebConfigKeyValueStatic("FrameworkApiURL")}Category/GetCategoryUserRolesDetails", RequestDetails);
    if (authorityApiResponse != null && authorityApiResponse.StatusCode == HttpStatusCode.OK && authorityApiResponse.Content.ReadAsStringAsync().Result != null)
    {
        var apiResponseDetails = authorityApiResponse.Content.ReadAsStringAsync().Result;
        lstRole = new List<ChangeRoleNotification>();
        lstRole = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ChangeRoleNotification>>(Convert.ToString(apiResponseDetails));
    }
}

Since I am working in converting a project into ASP.NET MVC 3-Tier I see a weird k__BackingField what does it mean?


Updated with Server Side Snippet of Response API:

[Route("Category/GetCategoryUserRolesDetails")]
[ActionName("GetCategoryUserRolesDetails")]
[HttpPost]
public HttpResponseMessage GetCategoryUserRolesDetails(CategoryRequestDetails categoryRequestDetails)
{
    List<ChangeRoleNotification> response = null;
    FrameworkAPIs.Log.LogClass.log.Debug("\nModule Name : Category;\nMethod Name : GetCategoryUserRolesDetails;\n Message :GetCategoryUserRolesDetails method starts ");
    string statusCode = String.Empty;
    DateTime StartTime = DateTime.Now;
    DateTime EndTime = DateTime.Now;
    Int64 WebServiceLogID = (new ServiceLogGenerator()).GenerateLog(categoryRequestDetails, "Category", "GetCategoryUserRolesDetails", StartTime, EndTime, "", "", null, 0);
    try
    {
        ManageCategory mangageCategory = new ManageCategory();
        if (categoryRequestDetails.UserID > 0)
            response = mangageCategory.GetCategoryUserRolesDetails(categoryRequestDetails);
        else
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid UserID");
    }
    catch (Exception ex)
    {
        FrameworkAPIs.Log.LogClass.log.Error("\nModule Name : Category;\nMethod Name : GetCategoryUserRolesDetails;\nError Message : " + ex.Message + ex.StackTrace + "\n");
        (new ServiceLogGenerator()).GenerateLog(null, "", "", StartTime, DateTime.Now, ex.StackTrace + ";\n" + ex.Message, "", null, WebServiceLogID);
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
    }
    (new ServiceLogGenerator()).GenerateLog(null, "", "", StartTime, DateTime.Now, "", "", response, WebServiceLogID);
    FrameworkAPIs.Log.LogClass.log.Debug("\nModule Name : Category;\nMethod Name : GetCategoryUserRolesDetails;\n Message :GetCategoryUserRolesDetails method ends\nResult :" + response);
    return Request.CreateResponse<List<ChangeRoleNotification>>(HttpStatusCode.OK, response);
}
Nɪsʜᴀɴᴛʜ ॐ
  • 2,756
  • 4
  • 33
  • 57
  • Where is this weird `k__BackingField` coming from? https://stackoverflow.com/questions/41816382/json-serialization-adding-k-backingfield-to-my-properties – mjwills Jul 01 '21 at 06:27
  • Probably there is something unusual or incorrect on the server side. That _k__BackingField_ seems to be the name assigned to the automatic backing field for [autoimplemented properties](https://stackoverflow.com/questions/8817070/is-it-possible-to-access-backing-fields-behind-auto-implemented-properties). It will be useful to see the code where these objects are serialized – Steve Jul 01 '21 at 06:33
  • Please show the type used on the server as the return type from that endpoint, as well as the server code that does the actual serialization. – Lasse V. Karlsen Jul 01 '21 at 06:44
  • Updated the forum post with Server side response implementation @LasseV.Karlsen – Nɪsʜᴀɴᴛʜ ॐ Jul 01 '21 at 06:56
  • 1
    If the `ChangeRoleNotification` on the server is the same as the one you've shown I can't see how that would end up serializing the backing fields. Have you configured json serialization in any way? – Lasse V. Karlsen Jul 01 '21 at 07:12
  • Before posting I have verified thrice. Yes indeed `ChangeRoleNotification` is same in both the ends and for testing I have added the property as `[Newtonsoft.Json.JsonProperty(PropertyName = "RoleName")]`. Configuration of Json serialization is left with default.. weird thing with `null` values... @LasseV.Karlsen – Nɪsʜᴀɴᴛʜ ॐ Jul 01 '21 at 08:02

1 Answers1

0

I think this is not an appropriate solution because of adding [JsonObject] attribute instead of [Serializable]. The issue with k__BackingField and null was solved. If any one knows exactly how to deal with this by adding [Serializable] they are always welcome

[Newtonsoft.Json.JsonObject]
public class ChangeRoleNotification
{
    public string RoleName { get; set; }
    public string RoleType { get; set; }
}

Updated with below approaches

Approach I: k__BackingField vanishes. But null seems to persist in server side

[Serializable]
public class ChangeRoleNotification
{
    private string RoleNameField;
    public string RoleName
    {
        get { return RoleNameField; }
        set { RoleNameField = value; }
    }
    private string RoleTypeField;
    public string RoleType
    {
        get { return RoleTypeField; }
        set { RoleTypeField = value; }
    }
}

Approach II (Worked): Both k__BackingField and null vanishes

[Serializable, DataContract]
public class ChangeRoleNotification
{
  [DataMember]
  public string RoleName { get; set; }

  [DataMember]
  public string RoleType { get; set; }
}

By adding [DataContract] in class and [DataMember] for property alone in only server side resolved in Approach II and I believe this one is most appropriate

Nɪsʜᴀɴᴛʜ ॐ
  • 2,756
  • 4
  • 33
  • 57
  • For Json serialization you don't need to apply `[Serializable]`, so if this is causing problems, just remove it. That attribute is as far as I know only used by binary serialization, aka `BinaryFormatter`. Have you tried removing all the attributes altogether? You should only need to add extra attributes if you want to change the serialization/deserialization away from the default, but in almost all cases, the default should be OK for this class. – Lasse V. Karlsen Jul 02 '21 at 07:07
  • Yeah! I believe without `[Serializable]` it would still work. In our project they are forced to contract this with every class properties without which they will never accept our work. If you find any implementations difference b/w with or without `[Serializable]` I could possibly raise objection or argue with any implementation part in our project @LasseV.Karlsen – Nɪsʜᴀɴᴛʜ ॐ Jul 02 '21 at 07:17
  • Sorry, I don't know why the presence of that attribute impacts the serialization of those properties vs. their backing fields. Again, AFAIK that attribute should only be used by BinaryFormatter and binary serialization. So unless someone has made some "clever" tricks regarding Json serialization that also uses this attribute, it shouldn't matter whether you have it or not. I also tested this, both Json.net and System.Text.Json serialized the properties, not the backing fields, as expected. – Lasse V. Karlsen Jul 02 '21 at 07:18
  • My guess would be that there is actually some configuration being done for one of the json serializers, and this is what is causing the issues. – Lasse V. Karlsen Jul 02 '21 at 07:21
  • And if you have lead programmers that dictate that you need to apply Serializable attribute to types that will be json serialized I would encourage you to find a new place to work. Cargo cult programmers are the worst to work with. At the very least stay informed and don't turn into one yourself. – Lasse V. Karlsen Jul 02 '21 at 07:23