Reputation: 213
Hi i have a C# model class. This class i need to pass as json response by setting his property . one property name Product of this class have type of another product class, when there is no data for Product i am getting all inner property value as blank but instead of that i want blank json property .
For Exp My Class is
public class Profile_BO
{
public int Id { get; set; }
public string Username { get; set; }
public Product product{ get; set; }
public class Product
{
public int Id { get; set; }
public string Type { get; set; }
}
}
i am initializing this class from C# data table like below : -
Profile_BO profile_BO = new Profile_BO();
foreach (DataRow dr in result.Tables[0].Rows)
{
profile_BO.Id = Convert.ToInt32(dr[0]);
profile_BO.Username = Convert.ToString(dr[1]);
}
Product product = new Product();
foreach (DataRow dr1 in result.Tables[1].Rows)
{
product.Id = Convert.ToInt32(dr1[0]);
product.Type = Convert.ToString(dr1[1]);
}
profile_BO.product = product;
Finally when i am passing as a response to method : -
public async Task<HttpResponseMessage> GetUserInfo(Profile_Request profile_Request)
{
return request.CreateResponse(HttpStatusCode.OK, profile_BO);
}
And when calling on client side i am getting response json if data is present in table like : -
{
"Id": "1",
"Username": "abc",
"product": {
"Id": "232",
"Type": "34cvdcbv"
}
}
But when i have no data in product table i am getting below : -
{
"Id": "1",
"Username": "abc",
"product": {
"Id": 0,
"Type": ""
}
}
But if no data i want output like below : -
{
"Id": "1",
"Username": "abc",
"product": {}
}
One other question is : - Is it right way for binding response model from dataset ?
Upvotes: 2
Views: 3083
Reputation: 6609
My previous answer doesn't contribute to your final question. So here is my edited solution.
A Better Solution
May be better solution is using Custom Message Handler.
A delegating handler can also skip the inner handler and directly create the response.
Custom Message Handler:
public class NullJsonHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var updatedResponse = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = null
};
var response = await base.SendAsync(request, cancellationToken);
if (response.Content == null)
{
response.Content = new StringContent("{}");
}
else if (response.Content is ObjectContent)
{
var contents = await response.Content.ReadAsStringAsync();
if (contents.Contains("null"))
{
contents = contents.Replace("null", "{}");
}
updatedResponse.Content = new StringContent(contents,Encoding.UTF8,"application/json");
}
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(updatedResponse);
return await tsc.Task;
}
}
Register the Handler:
In Global.asax
file inside Application_Start()
method register your Handler by adding below code.
GlobalConfiguration.Configuration.MessageHandlers.Add(new NullJsonHandler());
Now all the Asp.NET Web API
Response which contains null
will be replaced with empty Json
body {}
.
References:
Upvotes: 0
Reputation: 23937
the problem you are facing, is that you are initializing an instance of Product
regardless of the fact, that there might be no product at all. this results, to its properties getting initialized with default values. Int32
defaults to 0. System.String
as a reference type is null
.
Profile_BO profile_BO = new Profile_BO();
foreach (DataRow dr in result.Tables[0].Rows)
{
profile_BO.Id = Convert.ToInt32(dr[0]);
profile_BO.Username = Convert.ToString(dr[1]);
}
//I am assuming you only expect one row, since oyur model uses a single Product
//and no collection of products. No need for a loop then.
if(result.Tables[1].Rows.Count == 1) {
Product product = new Product();
var dr1 = result.Tables[1].Rows[0];
product.Id = Convert.ToInt32(dr1[0]);
product.Type = Convert.ToString(dr1[1]);
profile_BO.product = product;
}
This should result in the following JSON being returned:
{
"Id": "1",
"Username": "abc",
"product": null
}
EDIT: If you really must have product : {}
, then you need ot change your model.
public class Profile_BO
{
public int Id { get; set; }
public string Username { get; set; }
public object product { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
Declare product as an object
. Since all classes inherit from object, you can instantiate it as an object or Product, depending on your case:
if(result.Tables[1].Rows.Count == 1) {
Product product = new Product();
var dr1 = result.Tables[1].Rows[0];
product.Id = Convert.ToInt32(dr1[0]);
product.Type = Convert.ToString(dr1[1]);
profile_BO.product = product;
}
Or:
if(result.Tables[1].Rows.Count == 0) {
var product = new object();
profile_BO.product = product;
}
This will then result in:
{"Id":1,"Username":"Foo Bar","product":{}}
However I strongly advise to go with the first approach, because this will make testing and modifications easier, since you keep your strongly typed approach.
Upvotes: 2