.NET Core API 从 Web API 返回响应,不包括 cookie
Posted
技术标签:
【中文标题】.NET Core API 从 Web API 返回响应,不包括 cookie【英文标题】:.NET Core API returning response from Web API not including cookies 【发布时间】:2021-10-29 07:35:52 【问题描述】:我有一个 .NET Web API 控制器,其中包含以下登录方法:
[HttpPost]
[AllowAnonymous]
[Route("api/account/login")]
//Web API Controller method
public virtual async Task<IHttpActionResult> Login(LoginViewModel model)
SignInStatus response = await this.SignInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, shouldLockout: true);
if (response == SignInStatus.Success)
return Ok();
return BadRequest();
该方法返回一个HttpResponseMessage
,其中包含许多标头,包括Set-Cookie
。
我需要做的是从一个用 .NET Core 3.1 编写的控制器调用这个 Web API 控制器并返回 HttpResponseMessage
不变。这是我目前拥有的:
[HttpPost]
[Route("[action]")]
//.NET Core Controller method
public async Task<ActionResult> Login(LoginViewModel model)
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsync(WebApiControllerURI, new JsonContent(model));
return Ok(response);
但是,在来自 .NET Core 的响应中,Set-Cookie
不是标头,而是包含在响应正文中:
"Key": "Set-Cookie",
"Value": [
".AspNet.ApplicationCookie=...."
]
,
当我尝试显式返回 HttpResponseMessage
时得到相同的结果:
[HttpPost]
[Route("[action]")]
public async Task<HttpResponseMessage> Login(LoginViewModel model)
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsync(serverUrl + LoginUri, new JsonContent(model));
return response;
如何通过 .NET Core 控制器从 Web API 控制器返回响应并保留 Headers
属性中的标头?
【问题讨论】:
您是否尝试直接返回HttpResponseMessage
?示例:c-sharpcorner.com/UploadFile/dacca2/…
@Serhii 是的,我做到了。我更新了我的问题,表明我尝试明确返回 HttpResponseMessage
。
HttpClient
是什么?它是您构建的吗?你能给我们看一下代码吗?当 HTTPClient 收到它们时,您可以将这些 Header 添加到 HttpResponseMessage
。
@Alen.Toma 这是我正在使用的 System.Net.Http.HttpClient 类。
另外,您可以尝试创建自定义 IActionResult:***.com/a/54137811/8978576
【参考方案1】:
当您使用return Ok(response)
或仅使用return response
时,框架将获取HttpResponse
对象并将其序列化为json。
要代理响应,请查看此堆栈溢出问题Creating a proxy to another web api with Asp.net core
代码是这样的:
/* Copied from the linked stack overflow answer. Only part of the code since the linked question was about a full proxy. */
public static async Task CopyProxyHttpResponse(this HttpContext context, HttpResponseMessage responseMessage)
if (responseMessage == null)
throw new ArgumentNullException(nameof(responseMessage));
var response = context.Response;
response.StatusCode = (int)responseMessage.StatusCode;
foreach (var header in responseMessage.Headers)
response.Headers[header.Key] = header.Value.ToArray();
foreach (var header in responseMessage.Content.Headers)
response.Headers[header.Key] = header.Value.ToArray();
// SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response.
response.Headers.Remove("transfer-encoding");
using (var responseStream = await responseMessage.Content.ReadAsStreamAsync())
await responseStream.CopyToAsync(response.Body, _streamCopyBufferSize, context.RequestAborted);
[HttpPost]
[Route("[action]")]
//.NET Core Controller method
public async Task<ActionResult> Login(LoginViewModel model)
HttpResponseMessage response = await httpClient.PostAsync(WebApiControllerURI, new JsonContent(model));
await HttpContext.CopyProxyHttpResponse(response);
return Ok();
另一种选择是像 AspNetCore.Proxy 这样的库,具体取决于您需要代理多少。
【讨论】:
谢谢。我会看看 AspNetCore.Proxy 是否符合要求。 你从哪里得到_streamCopyBufferSize
?
@DavidBrower 不确定,这是直接从引用的堆栈答案中复制的。【参考方案2】:
如果你想在你的 API 请求中添加一个 cookie,那么有两种方法:
方法一:启动时
与静态 cookie 一起使用。
// Method 1 - In Startup
app.Use(async (context, next) =>
var cookieOptions = new CookieOptions()
Path = "/",
Expires = DateTimeOffset.UtcNow.AddHours(1),
IsEssential = true,
HttpOnly = false,
Secure = false,
;
context.Response.Cookies.Append("MyCookie", "TheValue", cookieOptions);
await next();
);
方法2:在API中
当你有一个改变值的 cookie 时使用:
[HttpPost("TestCookie")]
public async Task TestCookie(string cookieName, string cookieValue)
// Method 2 - Add to current context
var context = HttpContext;
var cookieOptions = new CookieOptions()
Path = "/",
Expires = DateTimeOffset.UtcNow.AddHours(1),
IsEssential = true,
HttpOnly = false,
Secure = false,
;
context.Response.Cookies.Append(cookieName, cookieValue, cookieOptions);
始终返回上下文,即使您没有返回语句。因此,您只需在上下文中设置 cookie 标头,它就会自动返回。
【讨论】:
以上是关于.NET Core API 从 Web API 返回响应,不包括 cookie的主要内容,如果未能解决你的问题,请参考以下文章
从 .NET Core Web API 调用 SalesForce API 并将响应反序列化为 c# 对象?
从 .NET Core 调用 Web API 到 .NET Framework
如何从 ASP.NET MVC 到 ASP.NET Core Web API 的 PUT?