-
-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: strong typed results #76
Comments
Can you give me a code snippet example of what you're trying to do? |
Below you can find an example of how (just a proof of concept) I used AspNetCore.Proxy to create sort of an api gateway that translates the incoming and outgoing messages. /// <summary>
/// Route for retrieving stock info for a given part number.
/// </summary>
/// <param name="partid">The identification of the part.</param>
/// <returns>Stock information for the given part in case the part is a known part.
/// Otherwise, a 404 error code is returned.</returns>
[HttpGet]
[Produces("application/json")]
[ProducesResponseType(typeof(PartStockInfo), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Problem), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(Problem), StatusCodes.Status404NotFound)]
[Route("api/part/{partid}/stock/")]
public Task GetPartStock([FromRoute] string partid)
{
var options = HttpProxyOptionsBuilder.Instance
.WithBeforeSend((context, requestmessage) => {
// This is the moment to change details in the call to the backend.
requestmessage.Headers.Accept.Clear();
requestmessage.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
return Task.CompletedTask;
})
.WithAfterReceive(async (context, responsemessage) =>
{
if(responsemessage.IsSuccessStatusCode)
{
// Todo: translate received xml response into json respons with different structure.
string content = await responsemessage.Content.ReadAsStringAsync();
var stockInfo = new PartStockInfo()
{
PartId = partid,
StockLevel = StockLevelIndicator.SUPERSEDED,
Successor = "100016"
};
responsemessage.Content = new StringContent(JsonSerializer.Serialize(stockInfo), System.Text.Encoding.UTF8, "application/json");
return;
}
var problem = new Problem()
{
Instance = Request.Path,
Status = (int)responsemessage.StatusCode,
};
if(responsemessage.StatusCode == System.Net.HttpStatusCode.NotFound)
{
problem.Title = $"The requested item ({partid}) cannot be found.";
}
responsemessage.Content = new StringContent(JsonSerializer.Serialize(problem), System.Text.Encoding.UTF8, "application/json");
return;
})
// Use the named http client with ntlm authentication.
.WithHttpClientName(Startup.HTTP_NTLM_CLIENT_NAME)
.WithShouldAddForwardedHeaders(false)
.Build();
// Call the backend
return this.HttpProxyAsync($"{config.Backend.BaseUrl}/Integration_Customer_Card('{partid}')", options);
} Please do tell me if what I'm trying to do (translating response messages) is not the intended use of AspNetCore.Proxy. |
Interesting: this might be possible, but it is not trivial since ASP.NET will try to pick up that return value and serialize it into the response. This library already does that by default from the proxied endpoint. What is the scenario that this would enable? You already have |
Well, for starters it would remove the need to add the response type to the 'ProducesResponse' attribute. But my main motiviation is that I like to use strong typed responses as much as possible because of the design time validation in the IDE. But as you already said, it is not a trivial feature. |
So, hmmm, I have a few ideas. It might be a bit complex, but I might be able to have Another option would be to create a new method for this specific purpose. |
Thanks for your effort @twitchax! In my opinion a generic 'overload' might be the best option because of compatibility with the existing version. If I can find some time, I'll fork your repository and try something myself. |
Ok: sounds good! |
Going to +1 this, but with a slightly different use case: I have a need to conditionally proxy for legacy API compatibility reasons. EDIT: further RTFM has me finding that I think As in something like this is a pattern I wish to use: [HttpGet]
[Route("some/horrible/classic.asp")] //API pretends/acts alike to a legacy classic ASP "api"
public async Task<IActionResult> FooClasicCompat([FromQuery] string someParam, [FromQuery] string fileName, ...)
{
if (someParam != null && someParam.Contains("legacy") // handwave: by some method "this needs to be proxied"
{
var legacyUrl = $"{this.GetLegacyUrlRoot}/some/horrible/classic.asp{this.Request.QueryString.Value}";
return await this.HttpProxyAsync(legacyUrl); // DESIRED THING SOMEHOW
}
//else, do the thing here in AspNetCore land instead, which can return multiple other possible IActionResults etc:
return File(this.FileActor.GetFileStream(fileName), this.MimeMap.GetMimeTypeByFileName(fileName); //or any other ActionResult impl/helpers
} That for other developers on my team it is very nice to stay in "ActionResult helper land" if we can help it. Just mostly asking/wondering about a way to tell/mock over a dummy IActionResult so that nothing else is written to the Response. |
Ok, makes sense. I will have to think on this. :) |
Is it possible to support strong typed results (IActionResult). I'm using 'WithAfterReceive' to rewrite the response. This is working well, but I would like to be able to use an ActionResult instead of 'Task', because then generation of Api documentation and other features would be supported better.
The text was updated successfully, but these errors were encountered: