JsonSerializationException: Unexpected end when deserializing array - c#

i'm getting problems with deserialization.
I heaven don't know if include entities is possible in server side. I have this includes in Client side but for that i was not using the get service.
WebAPI Controller
// GET: api/UnidadeCurricular
[HttpGet]
public IEnumerable<UnidadeCurricular> GetUnidadeCurricular()
{
return _context.UnidadeCurricular.Include(c => c.Departamento)
.Include(c => c.Curso)
.Include(c => c.NomeUC)
.ToList();
}
WebApp Controller
// GET: Unidade_curriculares
public async Task<IActionResult> Index()
{
List<UnidadeCurricular> unidade_curricular = new List<UnidadeCurricular>();
string path = "api/UnidadeCurricular";
HttpResponseMessage response = await HttpRequestBuilder.WebApiClient.GetAsync(path);
//Checking the response is successful or not which is sent using HttpClient
if (response.IsSuccessStatusCode)
{
unidade_curricular = await response.Content.ReadAsAsync<List<UnidadeCurricular>>();
}
return View(unidade_curricular);
}
Erro https://i.stack.imgur.com/bygnF.png
Hi want to get the information about the FK's that i have in this table and for that i just include the other in the context but when the service is call the error shows and i can't understand why it stops the desirialization.

Related

How can I send response from a controller method without returning from the method itself

I have created a method in my ASP.net core controller which is sending response back on returning.
How I can send multiple responses back without returning from the method.
[HttpGet]
[Route("{id:guid}")]
public async Task<IActionResult> GetWalkByIdAsync(Guid id)
{
try
{
var walk = await walkRepository.GetWalkByIdAsync(id);
if(walk == null)
{
return NotFound();
}
var walkResponse = mapper.Map<WalkResponse>(walk);
//////I want to send some additional responses back from here in the function//////
return Ok(walkResponse);
}
catch
{
return StatusCode(StatusCodes.Status500InternalServerError, "Sorry server down");
}
}
I am expecting to send additional responses before line "return Ok(walkResponse)"
You can not send multiple returns or responses at once. Instead, Package your target responses as one object package then perform necessary steps at response receiving end to process your responses accordingly.

Return List from a web API in C# [duplicate]

This question already has answers here:
Parsing Json rest api response in C# [duplicate]
(3 answers)
Closed 12 months ago.
tl;dr: I have an API that works in the browser, but I can't figure out how to return a list of items so I can traverse them in a List.
Long version:
I'm still struggling with API's and now I've hit another snag. I have the following code in my API:
[Route("api/[controller]")]
[ApiController]
public class ScheduleController : Controller
{
[HttpGet]
public IEnumerable<Schedule> GetAllSchedules()
{
using (ScheduleDataEntities entities = new ScheduleDataEntities())
{
return entities.Schedule.ToList();
}
}
[HttpGet("{id}")]
public Schedule GetIndividualSchedule(int id)
{
using (ScheduleDataEntities entities = new ScheduleDataEntities())
return entities.Schedule.FirstOrDefault(e => e.ScheduleID == id);
}
}
When I navigate to my localhost (https://localhost:7017/api/schedule) it returns the data just fine:
[{"userID":121,"weekDay":"Monday","startTime":"07:00:00","endTime":"07:15:00","createdDate":"2022-01-18T22:11:34.8966667","modifiedDate":"2022-01-18T22:11:34.8966667","active":false,"scheduleID":14414,"dayOfWeek":1,"tsType":"Normal"},
{"userID":94,"weekDay":"Wednesday","startTime":"08:45:00","endTime":"09:00:00","createdDate":"2021-11-03T13:50:50.26","modifiedDate":"2021-11-03T13:50:50.26","active":false,"scheduleID":13160,"dayOfWeek":3,"tsType":"Normal"}
...]
So far, so good. Now, I want to return the list to the client calling the API. I've made a simple test client that should get the list when I press a button:
client.Dispose();
client = new HttpClient();
client.BaseAddress = new Uri("https://localhost:7017/api/schedule/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
List<Schedule> list = GetScheduleList("https://localhost:7017/api/schedule");
//Do something with the list...
However, I can't figure out how this method should work:
static List<Schedule> GetScheduleList(string path)
{
List<Schedule> schedules = null;
HttpResponseMessage response = client.GetAsync(path);
return schedules;
}
Every tutorial I can find online, says to use GetAsync. However, that only works with the await keyword. Adding the await keyword means I have to add the async keyword to my method, which means I must return a Task<List> or a task-like type, which can't be converted to a List. If I return it as a Task, how can I then break it back down into my list of schedules?
I really feel like I've tried anything I've come across, so any help you can give is much appreciated.
try this
static async Task<List<Schedule>> GetScheduleList(string path)
{
var response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
var stringData = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<Schedule>>(stringData);
}
return null;
and fix the method call
List<Schedule> list = await GetScheduleList("https://localhost:7017/api/schedule");
or you can try, if you don't use async
List<Schedule> list = GetScheduleList("https://localhost:7017/api/schedule").Result;
did you try to start the web app in debug mode and find the return of the API ?
You can even use console.log to give more details;
Otherwise, I was there one day. it's CORS problem. you should add the header : Access-Control-Allow-Origin should have wildcard "*" as a value in order to be able to call https APIs on http servers.

How to create a GET route acting as a subscription route

I have a .Net 5 Web API and would like to create a GET endpoint (acting as a subscription) sending data every x seconds. I know that there are tools out there, e.g. SignalR, but I would like to know if it is possible to achieve the same result with a simple route. Maybe a stream could help ...
This is my example controller
[ApiController]
[Route("[controller]")]
public class MyController : ControllerBase
{
[HttpGet]
public OkResult SendDataEvery5Seconds()
{
return Ok(); // send back an initial response
// send data every 5 seconds
}
}
I don't know if this is possible with C# but I tried to create a working example using Node showing what I want to achieve:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.writeHead(200, {
'content-type': 'application/x-ndjson'
});
setInterval(() => {
res.write(JSON.stringify(new Date()) + '\n');
}, 5000);
})
app.listen(3000);
running curl -i http://localhost:3000 should write down a date every 5 seconds.
You can accomplish it like this.
Server code:
[HttpGet]
public async Task Get(CancellationToken ct = default)
{
Response.StatusCode = 200;
Response.Headers["Content-Type"] = "application/x-ndjson";
// you can manage headers of the request only before this line
await Response.StartAsync(ct);
// cancellation token is important, or else your server will continue it's work after client has disconnected
while (!ct.IsCancellationRequested)
{
await Response.Body.WriteAsync(Encoding.UTF8.GetBytes("some data here\n"), ct);
await Response.Body.FlushAsync(ct);
// change '5000' with whatever delay you need
await Task.Delay(5000, ct);
}
}
Corresponding client code (c# example):
var client = new HttpClient();
var response = await client.GetStreamAsync("http://localhost:5000/");
using var responseReader = new StreamReader(response);
while (!responseReader.EndOfStream)
{
Console.WriteLine(await responseReader.ReadLineAsync());
}

How to test a controller POST method which returns no data in response content in .NET Core 3.1?

i am new to integration tests. I have a controller method which adds a user to the database, as shown below:
[HttpPost]
public async Task<IActionResult> CreateUserAsync([FromBody] CreateUserRequest request)
{
try
{
var command = new CreateUserCommand
{
Login = request.Login,
Password = request.Password,
FirstName = request.FirstName,
LastName = request.LastName,
MailAddress = request.MailAddress,
TokenOwnerInformation = User
};
await CommandBus.SendAsync(command);
return Ok();
}
catch (Exception e)
{
await HandleExceptionAsync(e);
return StatusCode(StatusCodes.Status500InternalServerError,
new {e.Message});
}
}
As you have noticed my method returns no information about the user which has been added to the database - it informs about the results of handling a certain request using the status codes. I have written an integration test to check is it working properly:
[Fact]
public async Task ShouldCreateUser()
{
// Arrange
var createUserRequest = new CreateUserRequest
{
Login = "testowyLogin",
Password = "testoweHaslo",
FirstName = "Aleksander",
LastName = "Kowalski",
MailAddress = "akowalski#onet.poczta.pl"
};
var serializedCreateUserRequest = SerializeObject(createUserRequest);
// Act
var response = await HttpClient.PostAsync(ApiRoutes.CreateUserAsyncRoute,
serializedCreateUserRequest);
// Assert
response
.StatusCode
.Should()
.Be(HttpStatusCode.OK);
}
I am not sure is it enough to assert just a status code of response returned from the server. I am confused because, i don't know, shall i attach to assert section code, which would get all the users and check does it contain created user for example. I don't even have any id of such a user because my application finds a new id for the user while adding him/her to the database. I also have no idea how to test methods like that:
[HttpGet("{userId:int}")]
public async Task<IActionResult> GetUserAsync([FromRoute] int userId)
{
try
{
var query = new GetUserQuery
{
UserId = userId,
TokenOwnerInformation = User
};
var user = await QueryBus
.SendAsync<GetUserQuery, UserDto>(query);
var result = user is null
? (IActionResult) NotFound(new
{
Message = (string) _stringLocalizer[UserConstants.UserNotFoundMessageKey]
})
: Ok(user);
return result;
}
catch (Exception e)
{
await HandleExceptionAsync(e);
return StatusCode(StatusCodes.Status500InternalServerError,
new {e.Message});
}
}
I believe i should somehow create a user firstly in Arrange section, get it's id and then use it in Act section with the GetUserAsync method called with the request sent by HttpClient. Again the same problem - no information about user is returned, after creation (by the way - it is not returned, because of my CQRS design in whole application - commands return no information). Could you please explain me how to write such a tests properly? Have i missed anything? Thanks for any help.
This is how I do it:
var response = (CreatedResult) await _controller.Post(createUserRequest);
response.StatusCode.Should().Be(StatusCodes.Status201Created);
The second line above is not necessary, just there for illustration.
Also, your response it's better when you return a 201 (Created) instead of the 200(OK) on Post verbs, like:
return Created($"api/users/{user.id}", user);
To test NotFound's:
var result = (NotFoundObjectResult) await _controller.Get(id);
result.StatusCode.Should().Be(StatusCodes.Status404NotFound);
The NotFoundObjectResult assumes you are returning something. If you are just responding with a 404 and no explanation, replace NotFoundObjectResult with a NotFoundResult.
And finally InternalServerErrors:
var result = (ObjectResult) await _controller.Get(id);
result.StatusCode.Should().Be(StatusCodes.Status500InternalServerError);
You can use integrationFixture for that using this NuGet package. This is an AutoFixture alternative for integration tests.
The documented examples use Get calls but you can do other calls too. Logically, you should test for the status code (OkObjectResult means 200) value and the response (which could be an empty string, that is no problem at all).
Here is the documented example for a normal Get call.
[Fact]
public async Task GetTest()
{
// arrange
using (var fixture = new Fixture<Startup>())
{
using (var mockServer = fixture.FreezeServer("Google"))
{
SetupStableServer(mockServer, "Response");
var controller = fixture.Create<SearchEngineController>();
// act
var response = await controller.GetNumberOfCharacters("Hoi");
// assert
var request = mockServer.LogEntries.Select(a => a.RequestMessage).Single();
Assert.Contains("Hoi", request.RawQuery);
Assert.Equal(8, ((OkObjectResult)response.Result).Value);
}
}
}
private void SetupStableServer(FluentMockServer fluentMockServer, string response)
{
fluentMockServer.Given(Request.Create().UsingGet())
.RespondWith(Response.Create().WithBody(response, encoding: Encoding.UTF8)
.WithStatusCode(HttpStatusCode.OK));
}
In the example above, the controller is resolved using the DI described in your Startup class.
You can also do an actual REST call using using Refit. The application is self hosted inside your test.
using (var fixture = new RefitFixture<Startup, ISearchEngine>(RestService.For<ISearchEngine>))
{
using (var mockServer = fixture.FreezeServer("Google"))
{
SetupStableServer(mockServer, "Response");
var refitClient = fixture.GetRefitClient();
var response = await refitClient.GetNumberOfCharacters("Hoi");
await response.EnsureSuccessStatusCodeAsync();
var request = mockServer.LogEntries.Select(a => a.RequestMessage).Single();
Assert.Contains("Hoi", request.RawQuery);
}
}

could not get any response from api .net core

I want to pass the data on the browser in Json format using .net core API:
[HttpGet("{id}")]
public ActionResult<IEnumerable< tenMinutes>> Get(string id)
{
var result= _context.tenmins.Where(s => s.m_turbine_id == IPAddress.Parse(id) && s.m_time_stamp >= DateTime.Now.AddDays(-1)).Take(2).ToList();
return result;
}
the id is the ip address when i rutn the project and put the breacpont on result,i have results in List,but when it returns nothing on browser i get Can’t reach this page,what is the reason?

Categories

Resources