Json API isnt returning data - c#

I am trying to create a simple web API.
I have data going into the controller but I can't return it in the JSON API. I think the problem is returning the IEnumerable String.
BLL:
public IEnumerable<DTO.Gettod> Gettods()
{
DAL.todDataController tdc = new DAL.todDataController();
return tdc.GetToddMobiles();
}
Model:
public class TodViewModel
{
public IEnumerable<DTO.Gettod> ModelGetTod { get; set; }
}
Controller:
public IEnumerable<string> Get()
{
BLL.todManager tm = new BLL.todManager();
Models.TodViewModel tvm = new Models.TodViewModel();
tvm.ModelGetTod = tm.Gettods().ToArray();
return tvm as IEnumerable<string>;
}
JSON file returns only a Null but I'm expecting an Array.

The Correct Code is below, crediting: Bruno in the below answer:
public IHttpActionResult GetToddData()
{
BLL.todManager tm = new BLL.todManager();
Models.TodViewModel tvm = new Models.TodViewModel();
tvm.ModelGetTod = tm.Gettods().ToList();
//HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, tvm.ModelGetTod as IEnumerable<string>);
return Ok(tvm.ModelGetTod);
}

Try changing your controller to the below:
Edit: Changing the accepted answer to what worked for the user
public IHttpActionResult GetToddData () {
BLL.todManager tm = new BLL.todManager ();
Models.TodViewModel tvm = new Models.TodViewModel ();
tvm.ModelGetTod = tm.Gettods ().ToList ();
//HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, tvm.ModelGetTod as IEnumerable<string>);
return Ok (tvm.ModelGetTod);
}
Also, debug and see if you are getting the expected values in the tvm.ModelGetTod property.

Related

MVC - How to deserialize a Dictionary without having brackets [0] added to the key?

my deserialize Dictionary's key results in "brand[0]" when I send in "brand" to the api.
I have a class like this:
public class SearchRequest
{
public bool Html { get; set; } = false;
public Dictionary<string, HashSet<string>> Tags { get; set; }
}
// MVC Controller
[HttpPost]
public ActionResult Index(SearchRequest searchRequest)
{
...
}
And a json request like this that I post to the controller:
{
"html": true,
"tags": {
"brand": [
"bareminerals"
]
}
}
The binding seams to work and the searchRequest object is created but the resulting dictionary dose not have the key "brand" in it but insted the key "brand[0]" how can I preserve the real values I send in?
Edit: I need tags to be able to contain multiple tags, with multiple options, this was a simpel example.
One soulution to my problem is to create a custom model bind, so this is what am using now, but I dont understand why I need to, and I feel like there should be a easyer way? But am gonna leve It here anyhow.
public class FromJsonBodyAttribute : CustomModelBinderAttribute
{
public override IModelBinder GetBinder()
{
return new JsonModelBinder();
}
private class JsonModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var stream = controllerContext.HttpContext.Request.InputStream;
stream.Position = 0;
using (var reader = new StreamReader(stream))
{
var checkoutOrderDataStr = reader.ReadToEnd();
return JsonConvert.DeserializeObject(checkoutOrderDataStr, bindingContext.ModelType);
}
}
}
}
I'm not sure what is going on with your setup. You should not need a custom binder. I still think the problem is most likely with your calling code - whatever you're using as a client.
I'm using Asp.net Core 3.1. Here's what I threw together as a quick test.
Created Asp.net Core web application template with MVC. I declared two classes - a request POCO and a result POCO. The request was your class:
public class SearchRequest
{
public bool Html { get; set; } = false;
public Dictionary<string, HashSet<string>> Tags { get; set; }
}
The result was the same thing with a datetime field added just for the heck of it:
public class SearchResult : SearchRequest
{
public SearchResult(SearchRequest r)
{
this.Html = r.Html;
this.Tags = r.Tags;
}
public DateTime RequestedAt { get; set; } = DateTime.Now;
}
I Added a simple post method on the default HomeController.
[HttpPost]
public IActionResult Index([FromBody] SearchRequest searchRequest)
{
return new ObjectResult(new SearchResult(searchRequest));
}
I added a console Application to the solution to act as a client. I copied the two class definitions into that project.
I added this as the main method. Note you can either have the camel casing options on the request or not - asp.net accepted either.
static async Task Main(string[] _)
{
var tags = new[] { new { k = "brand", tags = new string[] { "bareminerals" } } }
.ToDictionary(x => x.k, v => new HashSet<string>(v.tags));
var request = new SearchRequest() { Html = true, Tags = tags };
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var json = JsonSerializer.Serialize(request, options);
Console.WriteLine(json);
using (var client = new HttpClient())
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("http://localhost:59276", content);
response.EnsureSuccessStatusCode();
var data = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<SearchResult>(data, options);
Console.WriteLine(data);
var keysSame = Enumerable.SequenceEqual(request.Tags.Keys, result.Tags.Keys);
var valuesSame = Enumerable.SequenceEqual(request.Tags.Values.SelectMany(x => x),
result.Tags.Values.SelectMany(x=>x));
Console.WriteLine($"Keys: {keysSame} Values: {valuesSame}");
}
}
This outputs:
{"html":true,"tags":{"brand":["bareminerals"]}}
{"requestedAt":"2020-10-30T19:22:17.8525982-04:00","html":true,"tags":{"brand":["bareminerals"]}}
Keys: True Values: True

Checking For Json response is true or false in unit testing with Nunit?

This is my method..
public ActionResult AddModelAliasData(ModalAliasModel modalAliasModel)
{
if (!ModelState.IsValid)
{
ModelState.LogModelStateError();
throw new BusinessException("COMMON_ERROR");
}
var response = _vehicleDataBusinessService.AddModelAliasData(modalAliasModel);
return Json(response);
}
As i am new to unit testing ... I am confused for some things, for the given above method in controller we are getting the json response in return. I want to check whether the return Json we are getting back has success true or false How should i do it???
The Response object result is
public class GetVehicleDataAliases : DefaultResponse
{
public List<SearchData> FindData { get; set; }
public List<VehicleDto> MakeDtos { get; set; }
}
The defaultResponse are Success , ErrorCode, ErrorMessage
I had wrote the unit test for this
[Test]
public void ShouldReturnJsonInAddMakeAlias()
{
var data = new GetVehicleDataAliases
{
MakeDtos = new List<VehicleDto>(),
Success = true,
FindData = new List<SearchData>()
};
mockVehicleDataBusinessService.Setup(x => x.AddMakeAliasData(It.IsAny<MakeAliasModel>())).Returns(() => data);
var vehicleDataController = new VehicleDataController(mockVehicleDataBusinessService.Object);
var result = vehicleDataController.AddMakeAliasData(makeAliasModel) as JsonResult;
Assert.AreEqual(data, result.Data);
}
But I am Able to clarify that is it the Right way to check for True or False Json result

Modify List<T> object to work with method that receives <T> or viceversa in C#

I need some suggestion on how to fix my code. I'm working on some existing project which has a bunch of dependencies, so the less I have to modify, the better. In this case, my controller needs BuildingReportModel as LIST, and at the end this controller returns this list to some view. My issue is when I try to call GetWSObject which receives a model/class, no a LIST. How would be the best way or best practices to make this code work? BuildingReportModel needs to be declare as List<> since I have some previous validation that can't be changed. Any suggestions?
List<BuildingReportModel> rc = new List<BuildingReportModel>();
BuildingWSObjects ws = new BuildingWSObjects();
rc = await ws.GetWSObject<BuildingReportModel>("all");
return View(rc);
public class BuildingReportModel
{
public string message1 { get; set; }
public string message2 { get; set; }
}
public class BuildingWSObjects
{
public async Task<T> GetWSObject<T>(string uriActionString)
{
T returnValue =
default(T);
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost/logger");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(uriActionString);
response.EnsureSuccessStatusCode();
returnValue = JsonConvert.DeserializeObject<T>(((HttpResponseMessage)response).Content.ReadAsStringAsync().Result);
}
return returnValue;
}
catch (Exception e)
{
throw (e);
}
}
}
I would modify BuildingWSObjects class and add new method:
public async Task<List<T>> GetWSObjects<T>(string uriActionString)
{
return new List<T> { await this.GetWSObject<T>(uriActionString)};
}
pass list to your GetWSObject than it will return you a list.
rc = await ws.GetWSObject<List<BuildingReportModel>>("all");

How to retrieve JsonResult data

I have the following Action in my layouts Controller
public JsonResult getlayouts(int lid)
{
List<layouts> L = new List<layouts>();
L = db.LAYOUTS.Where(d => d.seating_plane_id == lid).ToList()
return new JsonResult { Data = L, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
I am calling this Action from another controller like so:
layoutsController L = new layoutsController();
JsonResult result = L.getlayouts(lid);
My question is: how can I get the data from result object?
Well, have a look how you're building the object:
new JsonResult { Data = L, JsonRequestBehavior = JsonRequestBehavior.AllowGet }
You're setting the L variable to a property called Data. So just read that property:
List<layouts> L = (List<layouts>)result.Data;
There's nothing special about the fact that it's an MVC controller action.
You're simply calling a method which returns an object that was constructed in the method, and reading properties from that object. Just like any other C# code.
I have my class:
public class ResponseJson
{
public string message { get; set; }
public bool success { get; set; }
}
in my method SendEmail
private async Task<JsonResult> SendEmailAsync(ApplicationUser user, string returnUrl, string empleadoNombre, string pwdInic)
i will return my JsonResult
ResponseJson response = new ResponseJson();
response.success = true;
response.message = "OperaciĆ³n exitosa";
return new JsonResult( response);
to read the result returned from my SendEmail method
JsonResult emailSend = await SendEmailAsync(user, returnUrl, empleadoNombre, pwdInic);
ResponseJson response = new ResponseJson();
try
{
string json = JsonConvert.SerializeObject(emailSend.Value);
response = JsonConvert.DeserializeObject<ResponseJson>(json);
}
catch(Exception e)
{
}

What does HttpResponseMessage return as Json

I have a basic question about basics on Web Api. FYI, I have checked before but could not found what I was looking for.
I have a piece of code as described below these lines. Just like any other Method in general terms my method called: Post, it has to return something,a JSON for example, How do I do that.
Specifically, what am I supposed to write after the word " return " in order to get the 3 fields( loginRequest.Username,loginRequest.Password,loginRequest.ContractItemId ) as Json.
Coments: Do not worry about username,password and contractID are in comments, I do get their value in my LinQ. It's just the return whta I nened now, greetings to all who would like to throw some notes about this.
[System.Web.Http.HttpPost]
public HttpResponseMessage Post(LoginModel loginRequest)
{
//loginRequest.Username = "staw_60";
//loginRequest.Password = "john31";
//loginRequest.ContractItemId = 2443;
try
{
Membership member =
(from m in db.Memberships
where
m.LoginID == loginRequest.Username
&& m.Password == loginRequest.Password
&& m.ContractItemID == loginRequest.ContractItemId
select m).SingleOrDefault();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return ???;
}
Try this:
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new ObjectContent<Response>(
new Response() {
responseCode = Response.ResponseCodes.ItemNotFound
},
new JsonMediaTypeFormatter(), "application/json");
or just create another response from Request object itself.
return Request.CreateResponse<Response>(HttpStatusCode.OK,
new Response() { responseCode = Response.ResponseCodes.ItemNotFound })
You can also turn all your response types to JSON by updating the HttpConfiguration(Formatter.Remove) just remove the default xml serialization and put JSON.
You could perhaps create a LoginResponseModel class that you can use to send back information to the caller about the success/failure of the login attempt. Something like:
public class LoginResponseModel
{
public bool LoginSuccessful {get; set;}
public string ErrorMessage {get; set;}
public LoginResponseModel()
{
}
}
Then you can return this directly from the controller if you like:
[System.Web.Http.HttpPost]
public LoginResponseModel Post(LoginModel loginRequest)
{
...
return new LoginResponseModel() { LoginSuccessful = true, ErrorMessage = "" };
}
Or you can still use a HttpResponseMessage as return type, but send a LoginResponseModel as the json response:
[System.Web.Http.HttpPost]
public HttpResponseMessage Post(LoginModel loginRequest)
{
...
var resp = Request.CreateResponse<LoginResponseModel>(
HttpStatusCode.OK,
new LoginResponseModel() { LoginSuccessful = true, ErrorMessage = "" }
);
return resp;
}

Categories