最近我在ASP.NET Core中做了一个中间件CustomizedMiddleware,要说该中间件的功能也很简单,其实就是往HttpResponse中添加一个Cookie而已,但是我将添加Cookie的代码放在了next.Invoke(context)的后面,如下所示:

using Microsoft.AspNetCore.Http;
using System.Threading.Tasks; namespace Assembly.Middlewares
{
public class CustomizedMiddleware
{
private readonly RequestDelegate next; public CustomizedMiddleware(RequestDelegate next)
{
this.next = next;
} public async Task Invoke(Microsoft.AspNetCore.Http.HttpContext context)
{
//Do something...
await next.Invoke(context);
//Do something... context.Response.Cookies.Append("DemoCookie", "DemoValue");//在next.Invoke(context)后添加Cookie到Response
}
}
}

结果代码执行到 context.Response.Cookies.Append("DemoCookie", "DemoValue")时,老是抛出异常。

后来查了查资料,原来HttpResponse中有个很重要的属性HasStarted,HttpResponse.HasStarted属性会返回一个bool类型的值,表示当前Http请求的响应(HttpResponse)是否已经把Http头(Header)的内容发送给客户端浏览器了,如果HttpResponse.HasStarted返回true,我们就不能在HttpResponse上更改任何与Http头(Header)相关的内容了,例如Cookies、Headers、StatusCode等都无法做更改了,否则会抛出异常。此外,当HttpResponse.HasStarted返回true时,如果我们调用HttpResponse.Redirect方法进行跳转,这时HttpResponse.Redirect方法也会抛出异常报错:"System.InvalidOperationException: StatusCode cannot be set because the response has already started.",而且HttpResponse.Redirect不会产生任何效果,客户端浏览器页面也不会进行跳转。

结果我发现当上面的代码执行到context.Response.Cookies.Append("DemoCookie", "DemoValue")时,context.Response.HasStarted已经为true了,所以抛出了异常。

因此我将CustomizedMiddleware中间件的代码改为了如下:

using Microsoft.AspNetCore.Http;
using System.Threading.Tasks; namespace Assembly.Middlewares
{
public class CustomizedMiddleware
{
private readonly RequestDelegate next; public CustomizedMiddleware(RequestDelegate next)
{
this.next = next;
} public async Task Invoke(Microsoft.AspNetCore.Http.HttpContext context)
{
if (!context.Response.HasStarted)//先判断context.Response.HasStarted
{
context.Response.Cookies.Append("DemoCookie", "DemoValue");//在next.Invoke(context)前添加Cookie到Response
} //Do something...
await next.Invoke(context);
//Do something...
}
}
}

这次我把context.Response.Cookies.Append("DemoCookie", "DemoValue")放到了next.Invoke(context)的前面,并做了context.Response.HasStarted的判断,只有当context.Response.HasStarted为false时才添加Cookie,这次就没有抛出异常了,而且context.Response.Cookies.Append("DemoCookie", "DemoValue")也成功添加了Cookie到HttpResponse中。

所以这里总结下在ASP.NET Core的中间件中,尽量在next.Invoke(context)调用前做Response.Cookies和Response.Headers等属性的修改,修改前还要判断Response.HasStarted的值,如果是true,就不能做任何修改了。

ASP.NET Core中如果Response.HasStarted已经为true,就不能更改Response.Cookies和Response.Headers等属性的值了的更多相关文章

  1. ASP.NET Core中显示自定义错误页面-增强版

    之前的博文 ASP.NET Core中显示自定义错误页面 中的方法是在项目中硬编码实现的,当有多个项目时,就会造成不同项目之间的重复代码,不可取. 在这篇博文中改用middleware实现,并且放在独 ...

  2. ASP.NET Core中使用Graylog记录日志

    以下基于.NET Core 2.1 定义GrayLog日志记录中间件: 中间件代码: public class GrayLogMiddleware { private readonly Request ...

  3. ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解 (转载)

    “传导体” HttpContext 要理解 HttpContext 是干嘛的,首先,看图 图一 内网访问程序 图二 反向代理访问程序 ASP.NET Core 程序中,Kestrel 是一个基于 li ...

  4. ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解

    笔者没有学 ASP.NET,直接学 ASP.NET Core ,学完 ASP.NET Core MVC 基础后,开始学习 ASP.NET Core 的运行原理.发现应用程序有一个非常主要的 “传导体” ...

  5. 在ASP.NET Core中使用百度在线编辑器UEditor

    在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...

  6. ASP.NET Core 中文文档 第三章 原理(6)全球化与本地化

    原文:Globalization and localization 作者:Rick Anderson.Damien Bowden.Bart Calixto.Nadeem Afana 翻译:谢炀(Kil ...

  7. ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态

    原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...

  8. 在ASP.NET Core中使用Angular2,以及与Angular2的Token base身份认证

    注:下载本文提到的完整代码示例请访问:How to authorization Angular 2 app with asp.net core web api 在ASP.NET Core中使用Angu ...

  9. 如何在ASP.NET Core中实现CORS跨域

    注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...

随机推荐

  1. Redis 慢速入门(一)

    网上关于redis的入门文章其实已经很多了,这里仅仅以作者特独的视角来学习下redis相关的基础概念. 一切的基础 需要分清楚3个重要的概念,key,type,value. 这里的key为hello, ...

  2. Java知多少(19)访问修饰符(访问控制符)

    Java 通过修饰符来控制类.属性和方法的访问权限和其他功能,通常放在语句的最前端.例如: 1 public class className { 2 // body of class 3 } 4 pr ...

  3. Makefile基础

    1.规则 规则定义格式如下 目标 : 条件1 条件2 ... 命令1 命令2 ... 隐含规则和模式规则(略) 2.变量 Makefile变量像C的宏定义一样,代表一串字符,在取值的地方展开. 1)两 ...

  4. asp.net 通过ajax方式调用webmethod方法使用自定义类传参及获取返回参数

    实体类    public class User    {        public int Id { get; set; }        public string Name { get; se ...

  5. git gitk命令

    通过gitk命令,在单独的界面上查看项目源码在各个时间点上的代码提交情况. 各个commit 各个tag ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` 更多详细的介绍 ...

  6. unity与ios交替

    unity和ios的相互作用是更简单的.直接出口xcodeproject,这个大家都知道如何操作,如果需要二次开发ios码成unity,事实上,整合非常easy找到出口xcodeproject内iPh ...

  7. DB9_公头_母头_串口引脚定义及RS-232串口线制作方法

    RS-232连接线制作方法 材料及工具 一根双绞线(8芯).一个标准RJ45头.一个DB9孔型插头.一把RJ45专用工具.一个电烙铁及若干焊锡. 引脚定义 按以下管脚定义制作RJ45端头:I表示网络视 ...

  8. day_45_Django

    day45 内容回顾 #### 1. HTTP协议 tcp/IP协议 HTTP特性: 无连接 请求--响应模式 请求格式 响应格式 Django相关 Django下载 命令行: pip install ...

  9. VsCode删除多行操作

    1.下图是我们的文件 我想要一次性删除"how to delete this line" 所在的所有行,而其他行不删除 操作步骤 鼠标移动到 "how"上面,单 ...

  10. 守护线程daemon

    如下代码: from threading import Thread import time def func1(n): time.sleep(10) print(n) t = Thread(targ ...