I build some blazor app
and i want to have HttpGet like
person? x = await _httpClient.Get<person?>("url");
So from api if i return person then i want x to be it value
, if from api i return NULL
want to x be NULL
How to do this properly?
i have some httpclient with get like for example
public async Task<T> Get<T>(string uri, int timeOut = 100)
{
using var response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, uri), linkedCts.Token);
return await response.Content.ReadFromJsonAsync<T>();
}
}
but the compilator on this response.Content.ReadFromJsonAsync<T>()
says that possible null
return
But still if I return NULL
from api then it throws
The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.'
so does i need it to change to be of Task<T?>
so it may return null
? what is right path here?
what is best approach for this ? or am I missing something and this is not right way ?
Thank You and regards!
In any call into a data pipeline - Server or API - you should consider returning a result object, not a T. This solves the problem of returning a null, you always return a result object, and you can include status information, such as success/failure and a failure message.
Here's what I use:
public sealed record ItemQueryResult<TRecord> : IDataResult
{
public TRecord? Item { get; init;}
public bool Successful { get; init; }
public string Message { get; init; } = string.Empty;
private ItemQueryResult() { }
public static ItemQueryResult<TRecord> Success(TRecord Item, string? message = null)
=> new ItemQueryResult<TRecord> { Successful=true, Item= Item, Message= message ?? string.Empty };
public static ItemQueryResult<TRecord> Failure(string message)
=> new ItemQueryResult<TRecord> { Message = message};
}
For the record a list query result looks like this:
public sealed record ListQueryResult<TRecord> : IDataResult
{
public IEnumerable<TRecord> Items { get; init;} = Enumerable.Empty<TRecord>();
public bool Successful { get; init; }
public string Message { get; init; } = string.Empty;
public long TotalCount { get; init; }
private ListQueryResult() { }
public static ListQueryResult<TRecord> Success(IEnumerable<TRecord> Items, long totalCount, string? message = null)
=> new ListQueryResult<TRecord> {Successful=true, Items= Items, TotalCount = totalCount, Message= message ?? string.Empty };
public static ListQueryResult<TRecord> Failure(string message)
=> new ListQueryResult<TRecord> { Message = message};
}
IDataResult
provides a common interface for all results.
public interface IDataResult
{
public bool Successful { get; }
public string Message { get; }
}