如何获取ASP.Net Core 中的HttpStatus 代码?

How to acquire HttpStatus Codes in ASP.Net Core?

我正在 运行 浏览数组中的安全域和不安全域(http://https://)的列表,并希望 return 它们的状态代码.这在 ASP.Net Core 1.0 中怎么可能?

到目前为止,我有

foreach(var item in _context.URLs.ToList())
{
    // Do something here with item.Domain to check for status
    // For example, if item.Domain was https://example.com..
}

我尝试使用常规 ASP.Net 语法和这种方法:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(item.Domain);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

问题是,GetResponse 在 ASP.Net Core

中不起作用

任何人都可以帮我找到一个有效的解决方案,以便变量 returned 成为状态吗?

例如:200500404..

编辑 - 这是我的完整控制器和解决方案:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using MyApp.Models;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
namespace MyApp.Controllers.Api
{
    public class URLsController : Controller
    {
        private MyAppDBContext _context;

        public class newLink
        {
            public string Domain { get; set; }
            public HttpStatusCode Status { get; set; }
        }

        public async Task<HttpStatusCode> GetStatusCodes(string url)
        {
            var client = new HttpClient();
            var response = await client.GetAsync(url);

            return response.StatusCode;
        }

        public URLsController(MyAppDBContext context)
        {
            _context = context;
        }

        [HttpPost("api/URLs")]
        public async Task<IActionResult> Post(string url)
        {
            if (url != "")
            {
                // I pass a URL in through this API and add it to _context.URLs..
                // I execute a status code check on the URLs after this if statement
            }

            List<newLink> list = new List<newLink> ();

            foreach (var item in _context.URLs.ToList())
            {
                newLink t = new newLink();

                t.Domain = item.Domain;
                t.Status = await GetStatusCodes(item.Domain);

                list.Add(t);
            }

            return Ok(list);
        }
    }
}

此 returns 数组以这种格式返回:

[{"Domain":"https://example1.com/","Status":200},

{"Domain":"https://example2.com/","Status":200},

{"Domain":"https://example3.com/","Status":200}]

您可以使用 HttpClient,因为它更易于使用(您不需要像处理普通 HttpWebRequest 那样捕获非成功状态代码的 WebException 和然后从异常中提取 HTTP 状态代码)。

您可以编写一个辅助方法,给定 url 列表将 return 相应状态代码的列表。这将使您的代码更加解耦。不要违反单一职责原则。一个方法应该做不止一件特定的事情(在你的例子中,你将一些数据库调用和 HTTP 调用混合到一个方法中,这是不好的做法)。

public async Task<IList<HttpStatusCode>> GetStatusCodes(IList<string> urls)
{
    var client = new HttpClient();
    var result = new List<HttpStatusCode>();
    foreach (var url in urls)
    {
        var response = await client.GetAsync(url);
        result.Add(response.StatusCode);
    }

    return result;
}

备注 1:如果您尝试调用的 url 无法通过 DNS 解析,或者您的调用应用程序无法访问目标端口上指定地址的网络,您将不会获得任何状态代码出于显而易见的原因。你会得到一个很好的例外。考虑处理这个案例。在这种情况下,由您决定要在结果集合中 return 什么。

备注 2:仅仅为了确定 HTTP 状态代码而发出 GET 请求可能是一种浪费,因为您正在丢弃已经通过网络传输的响应主体。如果远程资源响应 HEAD 请求,这可能是确定服务器是否活动的更有效方法。但请谨慎考虑,因为它取决于您调用的 Web 端点的具体情况。

备注3:你肯定注意到这个方法是async。好吧,如果你打算在 .NET Core 下开发,你最好习惯它。您当然可以通过阻止调用线程来违反框架为您提供的 built-in 异步模式:

var urls = _context.URLs.ToList();
IList<HttpStatusCode> statusCodes = GetStatusCodes(urls).GetAwaiter().GetResult();

但这是一种极其糟糕的做法。一种更惯用的工作方式是在整个链中使所有方法异步,直到到达主要调用方法,该方法通常由框架本身提供并且也可以是异步的。例如,如果您在 Web API 操作中调用它,您可以简单地使其异步:

[HttpGet]
[Route("api/foos")]
public async Task<IActionResult> Get()
{
    var urls = _context.URLs.ToList();
    IList<HttpStatusCode> statusCodes = await GetStatusCodes(urls);
    return this.Ok(statusCodes);
}