对于asp.net–异步HTTP处理程序和在后台线程中使用HttpContext?感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解http异步调用,并且为您提供关于.NetCore在类库中使
对于asp.net – 异步HTTP处理程序和在后台线程中使用HttpContext?感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解http异步调用,并且为您提供关于.Net Core 在类库中使用当前 HttpContext、.net – 如何使单元测试可以使用HttpContext?、Android 中使用 HttpURLConnection 和 HttpClient 发送 Http 请求、ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解的宝贵知识。
本文目录一览:- asp.net – 异步HTTP处理程序和在后台线程中使用HttpContext?(http异步调用)
- .Net Core 在类库中使用当前 HttpContext
- .net – 如何使单元测试可以使用HttpContext?
- Android 中使用 HttpURLConnection 和 HttpClient 发送 Http 请求
- ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解
asp.net – 异步HTTP处理程序和在后台线程中使用HttpContext?(http异步调用)
此外,Using an HTTPContext across threads有一些关于HttpContext和线程的好信息.是不是所有的HttpContext都不是线程安全的,或只是像Response这样的项目?如果仅在读取模式下,多个后台线程可以访问Items属性吗?
解决方法
现在关于在异步请求中使用HttpContext;从不同的线程访问HttpContext会很危险,但在这种情况下,ASP.NET控制线程并确保只有一个线程正在处理请求.例如,当您继续手动(通过使用线程池或新的Thread())并将HttpContext提供给该线程,同时继续执行时,它会有所不同.
.Net Core 在类库中使用当前 HttpContext
HttpContext.Current 在 ASP.NET Core 中不再存在,但是 IHttpContextAccessor 可以在依赖关系中注入一个新的并用于检索当前 HttpContext
使用方法如下:
public class MyComponent : IMyComponent
{
private readonly IHttpContextAccessor _contextAccessor;
public MyComponent(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public string GetDataFromSession()
{
return _contextAccessor.HttpContext.Session.GetString(*KEY*);
}
}
.net – 如何使单元测试可以使用HttpContext?
我面临的问题是这个类的静态构造函数使用HttpContext.Current属性,因为我从类库运行我的单元测试,我在测试时没有HttpContext.
看看我的静态构造函数:
static UploadedFile() { if (HttpContext.Current == null) throw new Exception("web server not available"); HttpServerUtility server = HttpContext.Current.Server; // SET UploadedFileMappingFile Names: _resourceFileNames = new StringDictionary(); _resourceFileNames[_suppoertedFileStructures] = server.MapPath(SupportedUploadedFileStructures); _resourceFileNames[_supportedFileStructuresXSD] = server.MapPath(SupportedUploadedFileStructuresXSD); _resourceFileNames[UploadedFileEnum.UploadedFileFormatENUM.CSV.ToString()] = server.MapPath(UploadedFileColumnMap); }
我应该在我的测试环境中做什么,以便HttpContext.Current不会为null,我可以成功设置它:
HttpServerUtility server = HttpContext.Current.Server;
解决方法
例如,您可以调用该方法:
var wrapper = new HttpContextwrapper(HttpContext.Current); Foo.UploadedFile(wrapper);
在您的单元测试中(使用Rhino Mocks):
var contextMock = MockRepository.GenerateMock<HttpContextBase>(); // Todo: Define expectations on the mocked object Foo.UploadedFile(contextMock);
或者,如果您愿意,请使用Constructor Injection.
Android 中使用 HttpURLConnection 和 HttpClient 发送 Http 请求
在 android 应用程序中,可以使用 HttpURLConnection 发送 HTTP 请求。详见如下实例
1、activity_main.xml 布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:id="@+id/send_request"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送请求"
/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</ScrollView>
</LinearLayout>
2、MainActivity.java
package com.example.testhttp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
private Button sendRequest;
private TextView content;
private static final int SHOW_RESPONSE_CONTENT = 0;
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_RESPONSE_CONTENT:
String response = (String) msg.obj;
//显示到界面上
content.setText(response);
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取发送按钮
sendRequest = (Button) findViewById(R.id.send_request);
//获取TextView
content = (TextView) findViewById(R.id.content);
sendRequest.setOnClickListener(this);
}
//重写点击方法
@Override
public void onClick(View view) {
if(view.getId() == R.id.send_request){
//如果是点击发送按钮,则处理Http请求--使用HttpURLConnection
sendRequestWithHttpURLConnection();
}
}
/**
* 使用HttpURLConnection发送请求
*/
public void sendRequestWithHttpURLConnection(){
//新起一线程
new Thread(new Runnable() {
//处理逻辑
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL("http://www.baidu.com");
connection = (HttpURLConnection) url.openConnection();
//设置参数
//发送请求
connection.setRequestMethod("GET");
//连接超时时间
connection.setConnectTimeout(5000);
InputStream in = connection.getInputStream();
//对服务器返回的输入流进行读取
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder builder = new StringBuilder();
String line;
while((line = reader.readLine())!=null){
builder.append(line);
}
//使用Message
Message message = new Message();
message.what = SHOW_RESPONSE_CONTENT;
message.obj = builder.toString();
handler.sendMessage(message);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(connection!=null){
//断开连接
connection.disconnect();
}
}
}
}).start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
3、获取网络访问权限
修改 AndroidManifest.xml,添加:
<uses-permission android:name="android.permission.INTERNET"/>
4、结果
点击发送按钮,如下所示:
这就是服务器返回给我吗的 Html 代码。
如果是发送数据给服务器呢?看如下代码:
connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=yy&password=admin");
此外,可以使用 HttpClient 发送 Http 请求,
其他不变,在 MainActivity.java 类中添加方法 sendRequestWithHttpClient,如下:
private void sendRequestWithHttpClient(){
new Thread(new Runnable() {
@Override
public void run() {
try {
HttpClient httpClient= new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
//请求和相应成功
HttpEntity entity = httpResponse.getEntity();
//防止中文乱码
String responseText = EntityUtils.toString(entity,"utf-8");
Message message = new Message();
message.what = SHOW_RESPONSE_CONTENT;
message.obj = responseText.toString();
handler.sendMessage(message);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
修改 onClick 方法,如下:
//重写点击方法
@Override
public void onClick(View view) {
if(view.getId() == R.id.send_request){
//如果是点击发送按钮,则处理Http请求--使用HttpURLConnection
// sendRequestWithHttpURLConnection();
//如果是点击发送按钮,则处理Http请求--使用HttpClient
sendRequestWithHttpClient();
}
}
效果如下:
ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解
笔者没有学 ASP.NET,直接学 ASP.NET Core ,学完 ASP.NET Core MVC 基础后,开始学习 ASP.NET Core 的运行原理。发现应用程序有一个非常主要的 “传导体” HttpContext 。
赶忙写一下笔记先。
目录
“传导体” HttpContext
操作 HttpContext 前期准备
HttpContext 类型的属性和方法
HttpContext 对象实践与测试
- Request
- Response
- Item
“传导体” HttpContext
要理解 HttpContext 是干嘛的,首先,看图
图一 内网访问程序
图二 反向代理访问程序
ASP.NET Core 程序中,Kestrel 是一个基于 libuv 的跨平台 ASP.NET Core web 服务器。不清楚 Kerstrel 没关系,以后慢慢了解。
我们可以理解成,外部访问我们的程序,通过 Http 或者 Https 访问,例如 https://localhost:44337/Home/Index,需要通过一个网址,来寻向访问特定的页面。
访问页面时,会产生 Cookie、Seesion、提交表单、上传数据、身份认证等,外部与应用程序之间传导的导体就是 HttpContext。
总之,客户端跟 Web应用程序交互 是通过 HttpContext 传导的。
原理
ASP.NET Core 本质是一个控制台程序!ASP.NET Core 程序并不直接监听请求,而是通过依赖 HTTP Server ,来实现把各自请求转发到应用程序中。这个被转发的请求相当于我们日常浏览网页、上传文件、提交表单等的网络请求,这些请求会被包装,然后组合到 HttpContext 中。
就好像顾客到餐厅吃饭
- 需要先点菜、提出服务要求
- 服务员把你的菜单、需求送到厨房
- 厨师在加工好食品
- 服务员再把食品递给你
HttpContext 相当于这个服务员,她在前、后传递信息。
操作 HttpContext 前期准备
一般来说,我们主要写好Web程序,而无需理会 数据是怎么传导的。就好像两台电脑能够发送资料,我们用不着知道他们是通过无线Wifi、光纤还是铜线电缆传输的。
当有需要时,自然需要用~ 废话少说,先简单操作 HttpContext 了解下。后面接着解析这个对象。
如果你不需要练习,请直接跳过这一节内容。
- 打开 VS(2017)
- 新建项目
- ASP.NET Core Web 应用程序
- Web应用程序(模型视图控制器)
- 打开 Startup.cs ,在 ConfigureServices 中,加上
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); //先不用管这个是干嘛的
- 打开 HomeController.cs ,在顶部 using Microsoft.AspNetCore.Http; 把 HomeController 类替换成以下代码
public class HomeController : Controller { private IHttpContextAccessor _accessor; public HomeController(IHttpContextAccessor accessor) { _accessor = accessor; } [HttpGet] public IActionResult Index(int? id) { var httpcontext = _accessor.HttpContext; return View(httpcontext); } }
-
打开 Views/Home 目录,删除除 Index.cshtml 外的其它视图
- 把 Index.cshtml 的代码改成
@model Microsoft.AspNetCore.Http.HttpContext
@{
Layout = null;
}
到这里,准备已经完成。
以上代码的作用是把 HttpContext 对象 传递到 视图 中,直接在视图中使用。这样我们在理解时,只需在视图测试即可。
HttpContext 类型的属性和方法
在 ASP.NET Core 中,系统为每一个请求分配一个线程,HttpContext 针对的,就是一个线程。所以它的类、方法、属性等,都是针对当前请求起作用。
Properties(特性)
Authentication | 这个已经用不到了,这里只是列一下表。 用于身份认证(ASP.NET中用到),官方不建议在ASP.NT Core中使用。替代方案 Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions |
Connection | 获取有关此请求的基础连接的信息 |
Features | 获取此请求上可用的服务器和中间件提供的HTTP特性的集合 |
Items | 获取或设置可用于在该请求范围内共享数据的键/值集合 |
Request | 请求 |
RequestAborted | 通知此请求基础的连接何时中止,因此请求操作应取消 |
RequestServices | 获取或设置 IServiceProvider 集合,提供访问的请求的服务容器 |
Response | 响应 |
Session | 获取或设置用于管理此请求的用户会话数据的对象 |
TraceIdentifier | 获取或设置用于在跟踪日志中表示此请求的唯一标识符 |
User | 获取或设置此请求的用户 |
WebSockets | 获取一个对象,该对象管理此请求的WebSu套连接的建立 |
Item、Session、Response 等对象都是需要经常使用到的,下面笔者会详细实践。
HttpContext 对象实践与测试
Request
用于获取用户请求的对象,浏览器向Web程序提交表单、访问的URL、URL中包含的查询字符串、报文请求头等等。
Body | 获取或设置 RequestBody 流 |
ContentLength | 获取或设置 Content-Length 头 |
ContentType | 获取或设置Content-Type 头 |
Cookies | 获取或设置 Cookies |
Form | 获取或设置 表单内容 |
HasFormContentType | Checks the Content-Type header for form types. |
Headers | Gets the request headers. |
Host | 获取或设置主机头。可以包括端口 |
HttpContext | 获取或设置请求上下文 |
IsHttps | 检测当前是否HTTPS连接 |
Method | 获取或设置HTTP方法 |
Path | 获取或设置当前请求的路径,即URL |
PathBase | 获取或设置 RequestPathBase,就是URL前面那一段,如https://docs.microsoft.com |
Protocol | Gets or sets the RequestProtocol. |
Query | 查询字符串的集合 |
QueryString | 获取或设置用于在Request.Query中创建查询集合的原始查询字符串 |
Scheme | 获取或设置HTTP请求方案 |
试一试
打开 Index.Cshtml ,把以下代码加上去
(为了看得清楚一点,我加了表格)
<table>
<tr>
<td>RequestBody流</td>
<td> @Model.Request.Body</td>
</tr>
<tr>
<td>Content-Length头</td>
<td>@Model.Request.ContentLength</td>
</tr>
<tr>
<td>Content-Type头</td>
<td> @Model.Request.ContentType</td>
<tr>
<td>Cookies </td>
<td>@Model.Request.Cookies</td>
</tr>
<tr>
<td>IsHttps</td>
<td>@Model.Request.IsHttps</td>
</tr>
<tr>
<td>Host </td>
<td>@Model.Request.Host</td>
</tr>
</table>
运行Web程序,结果如下
在浏览器 F12 后,可以看到控制台的内容。请查看 下图的 1、3部分
Request 的其它使用方法,就不再赘述,你可以在视图中 @Model.Request. 加上需要测试的属性即可。
推荐别人关于 Request 的文章 https://www.cnblogs.com/Sea1ee/p/7240943.html
Response
Request 是 客户端向 Web 发送请求,而 Response 则是 Web 响应 客户端 的请求。这里笔者就不全部翻译了
使用Response可以直接影响服务器响应,设置响应内容、响应类型(发送网页、文件、图片等)、视图响应前重定向。
Response 应该在控制器中使用。具体使用方法笔者这里就不赘述。
Body | 获取或设置响应体流 |
ContentLength | Gets or sets the value for the |
ContentType | 获取或设置内容类型响应标头的值 |
Cookies | 获取一个对象,该对象可用于管理此响应的Cookie |
HasStarted | Gets a value indicating whether response headers have been sent to the client. |
Headers | Gets the response headers. |
HttpContext | Gets the HttpContext for this response. |
StatusCode | Gets or sets the HTTP response code. |
Response 的方法
OnCompleted(Func<Task>) |
在响应已发送到客户端之后添加要调用的委托 |
OnCompleted(Func<Object,Task>, Object) | 响应已发送到客户端之后添加要调用的委托 |
OnStarting(Func<Task>) | 在响应头将被发送到客户端之前添加要调用的委托 |
OnStarting(Func<Object,Task>, Object) | 在响应头将被发送到客户端之前添加要调用的委托 |
Redirect(String) | 向客户端返回一个临时重定向响应(HTTP 302) |
Redirect(String, Boolean) | 向客户端返回重定向响应(HTTP 301或HTTP 302) |
RegisterForDispose(IDisposable) | 处置(不可分)在请求完成处理后,注册主机处理的对象 |
Response 拓展方法
GetTypedHeaders(HttpResponse) | |
WriteAsync(HttpResponse, String, Encoding, CancellationToken) | 取消令牌使用给定的编码将给定文本写入响应体 |
WriteAsync(HttpResponse, String, CancellationToken) | 将给定文本写入响应体。UTF-8编码将被使用 |
Clear(HttpResponse) | |
SendFileAsync(HttpResponse, IFileInfo, Int64, Nullable<Int64>, CancellationToken) | 使用Sendfile 扩展发送给定的文件 |
SendFileAsync(HttpResponse, IFileInfo, CancellationToken) | Sends the given file using the SendFile extension. |
SendFileAsync(HttpResponse, String, Int64, Nullable<Int64>, CancellationToken) | Sends the given file using the SendFile extension. |
SendFileAsync(HttpResponse, String, CancellationToken) | Sends the given file using the SendFile extension. |

Item
如果你使用过 ViewData,就不难理解 HttpContext.Item
HttpContext.Item 是一个字典集合类型,具体类型为 IDictionary<TModel,TModel>。它的使用方法像 ViewData。(不要跟我说说你不知道 ViewBag、ViewData 是什么~)
打开 Index.Cshtml ,用下面代码复制替换
@model Microsoft.AspNetCore.Http.HttpContext
@{
Layout = null;
}
@{
List<string> i = new List<string>();
i.Add("a");
i.Add("b");
i.Add("c");
i.Add("d");
i.Add("e");
i.Add("f");
i.Add("g");
i.Add("h");
i.Add("i");
Model.Items["Test"] = i;
/*
Model.Items 是字典类型
这里设置 键 Test
值 i ,它的值是 List<string> 类型
*/
foreach(var item in Model.Items["Test"] as List<string>) //字典类型,必须先用 as 转为对应类型
{
<br> @item
}
}
结果
可以用 HttpContext.Item 来存储当前请求的意向有用的数据。
HttpContext 的其它方法使用这里不再赘述,需要注意的是,HttpContext 是针对一个请求的而产生的。
关于asp.net – 异步HTTP处理程序和在后台线程中使用HttpContext?和http异步调用的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于.Net Core 在类库中使用当前 HttpContext、.net – 如何使单元测试可以使用HttpContext?、Android 中使用 HttpURLConnection 和 HttpClient 发送 Http 请求、ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解的相关知识,请在本站寻找。
本文标签: