Complex parameter not getting to web api server - c#

I am trying a put operation from my mvc project, to a web api. I have two parameters one an integer type the other one is a complex type each time I make
a call to the server
the simple type gets to the server while the complex type is null. It works fine from postman... Please I need to know what i'm doing wrong
Here is my model
//Same with client side
public class PaymentTypeVM
{
public int Id { get; set; }
public string Name { get; set; }
}
Here is my client side code
public static async Task<RequestResult> EditPaymentType<T>(int id, T model)
{
var content = new { Model = model };
var str = JsonConvert.SerializeObject(content);
var resp = await _client.PutAsync($"api/admin/editpaymenttype/{id}", new StringContent(str, Encoding.UTF8, "application/json"));
var txt = await resp.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<RequestResult>(txt);
}
Here is the server code
[HttpPut]
[Route("editpaymenttype/{id}")]
public async Task<RequestResult> EditPaymentType(int id, [FromBody]PaymentTypeVM model)
{
if (!ModelState.IsValid)
{
return RequestResult.FailureResult(Messages.InvalidEntry);
}
var pType = await db.PaymentTypes.FindAsync(id);
if (pType == null) return RequestResult.FailureResult(Messages.NotFound);
pType.Name = model.Name ?? pType.Name;
await db.SaveChangesAsync();
return RequestResult.SuccessResult($"Payment type {Messages.EditSuccessful}");
}
Please I need a simplified answer cos i'm a novice, Thanks in advance.

You should change it.
var content = new { Model = model };
var str = JsonConvert.SerializeObject(content);
to
var str = JsonConvert.SerializeObject(model);
Don't send the model as nested object.

Assuming that you call EditPaymentType like this: EditPaymentType<PaymentTypeVM>
Change this part in the client...
var content = new { Model = model };
var str = JsonConvert.SerializeObject(content);
to this...
var str = JsonConvert.SerializeObject(model);
You're currently sending it a serialized object that has a property of Model, with the value being your model, but then trying to map it to a parameter of type PaymentTypeVM when it's deserialized on the server.
If the types don't match then it can't deserialize the body contents into the parameter, and it ends up being null.

the HttpClient sends a parameter with this structure:
{
Model =
{
Id = 1,
Name = "Name"
}
}
while, the WebApi server expects a parameter like this:
{
Id = 1,
Name = "Name"
}

Related

In gRPC unable to bind enum values from message to dontnet core Dto

I need to define a string array type dataType in Grpc message. not sure how to do. right now i am doing it as a
repeated string Title= 1,
here i need name field as string array Type. But it is showing error that it is, field is readonly type when bind data in it:
public override async Task<UserResponse> CreateUser(
UserModel request, ServerCallContext context)
{
var eventResponse = new UserResponse();
var createCmd = new CreateUserCommand
{
Model = new UserDto
{
Title = request.Title,
Id = request.Id,
}
}
}
here in title i need to bind data
The generated code from protoc here gives you something like:
private readonly RepeatedField<string> title_ = new RepeatedField<string>();
[DebuggerNonUserCodeAttribute]
public RepeatedField<string> Title {
get { return title_; }
}
So: Title is indeed read-only. This means that instead of assigning it, you should explore what APIs exist for adding to it - i.e.
var user = new UserDto
{
Id = request.Id,
}
user.Title.Add(request.Title);
// or AddRange, etc
You may still be able to use initializer syntax, too:
new UserDto
{
Id = request.Id,
Title = { request.Title }
}
(which is an .Add)

C# - Unit Test for Json Data

Please how can I write a Unit Test for crud api returning Json
//Get all cli
[HttpGet]
public IHttpActionResult GetAllCli()
{
var data = db.cli.ToList();
return Json(data);
}
// Post method for GetAllCli
[HttpPost]
public IHttpActionResult Post()
{
var pu = new client
{
FirstName = first,
LastName = last,
Address = addre,
};
db.cli.Add(pu);
db.SaveChanges();
return Json(new { StatusCode = "Success" });
}
Wasn't sure of how to go forward with this
[TestMethod]
public void GetAll_ShouldReturnAllCli()
{
var contrller = new CliController();
var result = contrller.GetAllCli() as JsonResult;
//result is null after this line
//Is there a way to get result count of the json dat
Assert.AreEqual(5, result);
}
result is always null.
Is there a way to get the count result of the json dat
In Web API Json method returns generic JsonResult<T> (from System.Web.Http.Results) and not JsonResult (from System.Web.Mvc) that's why you get null during cast. In order to cast to generic type you should not use anonymous type but define a class for result
public class Result
{
public string StatusCode { get; set; }
}
Then your test will look like this
using System.Web.Http.Results;
//...
var contrller = new CliController();
var result = contrller.GetAllCli() as JsonResult<Result>;
Update your test method as below, if you are only stuck at getting a count add more description in your question to make it clear what you have and what you are trying to do
[TestMethod]
public void GetAll_ShouldReturnAllCli()
{
var contrller = new CliController();
var result = contrller.GetAllCli() as JsonResult;
var Originalresult = JsonHelper.GetJsonObjectRepresentation<IDictionary<string, object>>(result);
Assert.AreEqual(5, Originalresult.count());
}

How to return data in object format for web api?

I have to return data in json format but it says cannot implicitly convert type string to system.collection.generic.list(object).
[HttpGet]
public List<object> GetAllCompanies2()
{
List<object> myCo = DefCompany.AllDefCompany2;
// return myCo----------> works
string json = JsonConvert.SerializeObject(myCo);
return json; ------- > not works conversion error & i need this
}
I tried tostring() and many other ways but nothing worked. How can I convert string to object?
Here is my function code AllDefCompany2
public static List<object> AllDefCompany2
{
get
{
using (var db = new RPDBEntities())
{
return db.DefCompanies.Select(b => new
{
Id = b.Id,
CurrentCurrencyCode = b.CurrentCurrencyCode,
ShortName = b.ShortName,
FullName = b.FullName,
ContactPerson = b.ContactPerson,
Address1 = b.Address1,
CompanyCity = b.CompanyCity,
CompanyState = b.CompanyState,
CompanyCountry = b.CompanyCountry,
ZipPostCode = b.ZipPostCode,
TelArea = b.TelArea
}).ToList<object>();
}
}
}
this code helps me to solve both api and kendo problem
[HttpGet]
public List<object> GetAllCompanies2()
{
List<object> myCo = DefCompany.AllDefCompany2;
object json = JsonConvert.SerializeObject(myCo);
return json;
}
here is configuration settings
using System.Data.Entity;
namespace RpManticSolAPI
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
}
}
}
return JsonConvert.SerializeObject(myCo);
You can convert string to object, but what you are trying to do in the code shown is convert it to a List<object>. You can try calling AsEnumerable or ToList on the json variable.
But if what you want to do is return a string, why not change the return type of the method?
[HttpGet]
public string GetAllCompanies2()
{
List<object> myCo = DefCompany.AllDefCompany2;
// return myCo----------> works
string json = JsonConvert.SerializeObject(myCo);
return json; ------- > not works conversion error & i need this
}
Try this. Need to change function return type based on whether you return list of objects or string (in this case json)

Lose MongoDB ObjectId value when passing through Actions

In my MVC Controller, I have this code (after adding an object, I redirect user to edit that object):
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Add()
{
MongoDataContext dc = new MongoDataContext();
var model = new ModelObj();
dc.Models.Insert(model);
return this.RedirectToAction("Edit", new { pId = model.Id, });
}
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Edit(ObjectId? pId)
{
MongoDataContext dc = new MongoDataContext();
var model = dc.Models.FindOneById(pId);
if (model == null)
{
Session["error"] = "No model with this ID found.";
return this.RedirectToAction("");
}
return this.View(model);
}
However, pId is always null, making the FindOneById always return null. I have debugged and made sure that the Id had value when passing from Add Action. Moreover, I tried adding a testing parameter:
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Add()
{
MongoDataContext dc = new MongoDataContext();
var model = new ModelObj();
dc.Models.Insert(model);
return this.RedirectToAction("Edit", new { pId = model.Id, test = 10 });
}
[PrivilegeRequirement("DB_ADMIN")]
public ActionResult Edit(ObjectId? pId, int? test)
{
MongoDataContext dc = new MongoDataContext();
var model = dc.Models.FindOneById(pId);
if (model == null)
{
Session["error"] = "No model with this ID found.";
return this.RedirectToAction("");
}
return this.View(model);
}
When I debug, I received the test parameter in Edit Action with value of 10 correctly, but pId is null. Please tell me what I did wrong, and how to solve this problem?
I would suspect that the ObjectId is not serializing/deserializing correctly. Given that it doesn't make for a great WebAPI anyway, I generally use a string and convert within the method to an ObjectId via the Parse method (or use TryParse):
public ActionResult Edit(string id, int? test)
{
// might need some error handling here .... :)
var oId = ObjectId.Parse(id);
}
You can use ToString on the ObjectId to convert it to a string for calling:
var pId = model.Id.ToString();

Linq object properties disappear after serialization

I'm trying to understand the included code snippets behavior, it doesn't work as I'd expect. Here is what I'm doing:
Serialize a LINQ object to JSON
Deserialize the JSON at (1) back in its initial type
Validate that each property are still in the Object
I serialize the object from (2) back to JSON
Print the json from (4) and visually inspect it
My issue is that at (5), any LINQ entity that is a property of the main LINQ object is gone, even tho it was still there when on validation at (3). All my LINQ classes are LINQ to SQL. I am using Newtons JSON.Net library. I tried the same type of logic with non-linq object and the defect seen at (5) doesn't occur.
var infoId = Guid.NewGuid();
var alertId = Guid.NewGuid();
var info = new Info();
info.InfoId = infoId;
var alert = new Alert();
alert.AlertId = alertId;
alert.Infos.Add(info);
var json = JsonConvert.SerializeObject(alert);
Debug.WriteLine(json); //All looking good, nothing missing
var deserializedObject = JsonConvert.DeserializeObject<Alert>(json);
Assert.AreEqual(alertId, deserializedObject.AlertId); //Assert is valid
Assert.AreEqual(infoId, deserializedObject.Infos[0].InfoId); //Assert is valid
var json2 = JsonConvert.SerializeObject(deserializedObject);
Debug.WriteLine(json2); //Infos is gone
Update:
I have done some debbugging, and in the Serialization of deserializedObject
var json2 = JsonConvert.SerializeObject(deserializedObject);
I see the following when reaching the Info Serialization step (next code snipped):
this.serializing is true
this._Infos.HasLoadedOrAssignedValues is false
The get return null is called. (get returns the null value)
If I put a breakpoint, and put my cursor on the return this._Infos I actually see the object that It should return ...
[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Alert_Info", Storage="_Infos", ThisKey="AlertId", OtherKey="AlertId")]
[global::System.Runtime.Serialization.DataMemberAttribute(Order=15, EmitDefaultValue=false)]
public EntitySet<Info> Infos
{
get
{
if ((this.serializing && (this._Infos.HasLoadedOrAssignedValues == false)))
{
return null;
}
return this._Infos;
}
set
{
this._Infos.Assign(value);
}
}
Update:
This leads me to believe that I might need to find a way to modify the default value of HasLoadedOrAssignedValues when it is being deserialized from Newtons Json.Net.
I also found a dirty fix, which I don't really like that seems to be working:
var deserializedObject = JsonConvert.DeserializeObject<EasAlert>(json);
var list = new List<EasInfo>();
deserializedObject.EasInfos.SetSource(list); //<--- Fix, the Info will show up in json2
Assert.AreEqual(alertId, deserializedObject.AlertId);
Assert.AreEqual(infoId, deserializedObject.EasInfos[0].InfoId);
I was trying Microsoft's JavaScriptSerializer, and it worked fine. Code and output can be found below.
Could it be a bug in Newton's?
void Main()
{
var infoId = Guid.NewGuid();
var alertId = Guid.NewGuid();
var info = new Info();
info.InfoId = infoId;
var alert = new Alert();
alert.AlertId = alertId;
alert.Infos.Add(info);
var jss = new JavaScriptSerializer();
var json = jss.Serialize(alert); //JsonConvert.SerializeObject(alert);
Debug.WriteLine(json); //All looking good, nothing missing
var deserializedObject = jss.Deserialize<Alert>(json); //JsonConvert.DeserializeObject<Alert>(json);
(alertId == deserializedObject.AlertId).Dump(); //Assert is valid
(infoId == deserializedObject.Infos[0].InfoId).Dump(); //Assert is valid
var json2 = jss.Serialize(deserializedObject); //JsonConvert.SerializeObject(deserializedObject);
Debug.WriteLine(json2); //Infos is gone - NOT GONE!
}
public class Alert
{
public Guid AlertId { get; set; }
public List<Info> Infos { get; set; }
public Alert()
{
Infos = new List<Info>();
}
}
public class Info
{
public Guid InfoId { get; set; }
}
Output:
{"AlertId":"0340e855-065c-4ac7-868e-5999fa4b7862","Infos":[{"InfoId":"31e269a1-4354-423d-84bc-62f6dc06b10f"}]}
True
True
{"AlertId":"0340e855-065c-4ac7-868e-5999fa4b7862","Infos":[{"InfoId":"31e269a1-4354-423d-84bc-62f6dc06b10f"}]}
check Alert class (constructor)
public class Alert{
public Guid AlertId{get;set;}
public List<Info> Infos {get;set;}
public Alert() {
Infos = new List<Info>();
}
}
looks like you are missing List init
even with EntitySet

Categories