【Vue】VUE引用element-ui報錯Uncaught TypeError: Cannot read properties of undefined (reading ‘prototype‘)-CSDN博客

mikel阅读(521)

来源: 【Vue】VUE引用element-ui報錯Uncaught TypeError: Cannot read properties of undefined (reading ‘prototype‘)-CSDN博客

报错代码如下:
app.js:160 Uncaught TypeError: Cannot read properties of undefined (reading ‘prototype’)
at eval (types.js?8ad0:39:1)
at ./node_modules/element-ui/lib/utils/types.js (chunk-vendors.js:834:1)
at __webpack_require__ (app.js:157:33)
at fn (app.js:402:21)
at eval (util.js?40a4:19:1)
at ./node_modules/element-ui/lib/utils/util.js (chunk-vendors.js:845:1)
at __webpack_require__ (app.js:157:33)
at fn (app.js:402:21)
at eval (format.js?5a92:49:1)
at ./node_modules/element-ui/lib/locale/format.js (chunk-vendors.js:501:1)

报错原因:
因为我创建的是VUE3项目,VUE的版本为3.2.13,而element-ui只适用于VUE2项目,经过我查询,element-plus适用于VUE3项目。为了更加充分的证明这个问题,我去创建了一个VUE2项目,版本为2.6.14,是能够引用element-ui。

解决方案
1.先确认自己项目是VUE2项目还是VUE3项目,在package.json文件里面查看,如下图所示。

2.根据VUE版本,执行以下其中一步
A.如果是VUE2项目,安装element-ui,指令如下

npm i element-ui –save

B.如果是VUE3项目,安装element-plus,指令如下

npm i element-plus –save

总结
Vue2项目安装element-ui,VUE3项目安装element-plus。
————————————————
版权声明:本文为CSDN博主「里奥♚」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_46533551/article/details/129042824

发生一个或多个错误,未能启动调试适配器。可以在输出窗口中查看额外的信息。 Visual Studio 2019_发生一个或多个错误,未能启动调试适配器-CSDN博客

mikel阅读(416)

来源: 发生一个或多个错误,未能启动调试适配器。可以在输出窗口中查看额外的信息。 Visual Studio 2019_发生一个或多个错误,未能启动调试适配器-CSDN博客

发生一个或多个错误。

未能启动调试适配器。可以在输出窗口中查看额外的信息。

Cannot connect to runtime process, timeout after 10000 ms (reason: Cannot connect to the target: connect ECONNEREFFUSED127.0.0.1:2015).

原因:开启了vs的JavaScript的调试模式,导致的。

This is due to VS Debug option: Debug JavaScript turned on, but the browser in question is not allowing debugger to connect to a special port. IMHO this way of debug JavaScript never was any good – browser JS debug tools are far better.

When I turned it off, both VS2017 and 2019 debuggers started to work (without JS debugging of coarse)

解决方法:关闭vs的JavsScript调试功能即可。

【工具】-》【选项】-》【调试】-》【常规】 找到javascript的调试项,关闭即可。

在 ASP.NET Core 中启用跨源请求 (CORS) | Microsoft Learn

mikel阅读(402)

来源: 在 ASP.NET Core 中启用跨源请求 (CORS) | Microsoft Learn

作者:Rick Anderson 和 Kirk Larkin

本文介绍如何在 ASP.NET Core 应用中启用 CORS。

浏览器安全性可防止网页向不处理网页的域发送请求。 此限制称为同域策略。 同域策略可防止恶意站点从另一站点读取敏感数据。 有时,你可能希望允许其他网站向自己的应用发出跨源请求。 有关详细信息,请参阅 Mozilla CORS 文章

跨源资源共享 (CORS):

  • 是一种 W3C 标准,允许服务器放宽同源策略。
  • 不是安全功能,CORS 放松了安全限制。 允许 CORS 并不会使 API 更安全。 有关详细信息,请参阅 CORS 的工作原理
  • 允许服务器显式允许某些跨源请求,同时拒绝其他请求。
  • 比早期技术(如 JSONP)更安全、更灵活。

查看或下载示例代码如何下载

同源

如果两个 URL 具有相同的方案、主机和端口 (RFC 6454),则它们同源。

这两个 URL 同源:

  • https://example.com/foo.html
  • https://example.com/bar.html

这些 URL 的源与前两个 URL 不同:

  • https://example.net:不同的域
  • https://www.example.com/foo.html:不同的子域
  • http://example.com/foo.html:不同的方案
  • https://example.com:9000/foo.html:不同的端口

启用 CORS

有三种方法可以启用 CORS:

将 [EnableCors] 属性与命名策略一起使用可在限制支持 CORS 的终结点方面提供最佳控制。

 警告

UseCors 必须按正确的顺序调用。 有关详细信息,请参阅中间件顺序。 例如,使用 UseResponseCaching 时,必须在 UseResponseCaching 之前调用 UseCors

以下各部分详细介绍了每种方法。

具有命名策略和中间件的 CORS

CORS 中间件处理跨源请求。 以下代码将 CORS 策略应用于具有指定源的所有应用终结点:

C#

var  MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy  =>
                      {
                          policy.WithOrigins("http://example.com",
                                              "http://www.contoso.com");
                      });
});

// services.AddResponseCaching();

builder.Services.AddControllers();

var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors(MyAllowSpecificOrigins);

app.UseAuthorization();

app.MapControllers();

app.Run();

前面的代码:

  • 将策略名称设置为 _myAllowSpecificOrigins。 策略名称是任意的。
  • 调用 UseCors 扩展方法并指定 _myAllowSpecificOrigins CORS 策略。 UseCors 添加 CORS 中间件。 对 UseCors 的调用必须放在 UseRouting 之后,但在 UseAuthorization 之前。 有关详细信息,请参阅中间件顺序
  • 使用 lambda 表达式调用 AddCors。 lambda 采用 CorsPolicyBuilder 对象。 本文稍后将介绍配置选项,如 WithOrigins
  • 为所有控制器终结点启用 _myAllowSpecificOrigins CORS 策略。 要将 CORS 策略应用于特定终结点,请参阅终结点路由
  • 使用响应缓存中间件时,请在 UseResponseCaching 之前调用 UseCors

对于终结点路由,CORS 中间件必须配置为在对 UseRouting 和 UseEndpoints 的调用之间执行。

有关测试与前面代码类似的代码的说明,请参阅测试 CORS

AddCors 方法调用将 CORS 服务添加到应用的服务容器:

C#

var  MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy  =>
                      {
                          policy.WithOrigins("http://example.com",
                                              "http://www.contoso.com");
                      });
});

// services.AddResponseCaching();

builder.Services.AddControllers();

var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors(MyAllowSpecificOrigins);

app.UseAuthorization();

app.MapControllers();

app.Run();

有关详细信息,请参阅本文档中的 CORS 策略选项

可以链接 CorsPolicyBuilder 方法,如以下代码所示:

C#

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(MyAllowSpecificOrigins,
                          policy =>
                          {
                              policy.WithOrigins("http://example.com",
                                                  "http://www.contoso.com")
                                                  .AllowAnyHeader()
                                                  .AllowAnyMethod();
                          });
});

builder.Services.AddControllers();

var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors(MyAllowSpecificOrigins);

app.UseAuthorization();

app.MapControllers();

app.Run();

注意:指定的 URL 不能包含尾部斜杠 (/)。 如果 URL 以 / 结尾,则比较返回 false,并且不返回任何标头。

 警告

UseCors 必须位于 UseRouting 之后和 UseAuthorization 之前。 这是为了确保 CORS 标头包含在已授权和未经授权的调用的响应中。

UseCors 和 UseStaticFiles 顺序

通常,在 UseCors 之前调用 UseStaticFiles。 使用 JavaScript 跨站点检索静态文件的应用必须在 UseStaticFiles 之前调用 UseCors

具有默认策略和中间件的 CORS

以下突出显示的代码启用默认 CORS 策略:

C#

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(
        policy =>
        {
            policy.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });
});

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors();

app.UseAuthorization();

app.MapControllers();

app.Run();

前面的代码将默认 CORS 策略应用于所有控制器终结点。

通过终结点路由启用 Cors

对于终结点路由,可以使用 RequireCors 扩展方法集基于每个终结点启用 CORS:

C#

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy =>
                      {
                          policy.WithOrigins("http://example.com",
                                              "http://www.contoso.com");
                      });
});

builder.Services.AddControllers();
builder.Services.AddRazorPages();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/echo",
        context => context.Response.WriteAsync("echo"))
        .RequireCors(MyAllowSpecificOrigins);

    endpoints.MapControllers()
             .RequireCors(MyAllowSpecificOrigins);

    endpoints.MapGet("/echo2",
        context => context.Response.WriteAsync("echo2"));

    endpoints.MapRazorPages();
});

app.Run();

在上述代码中:

  • app.UseCors 启用 CORS 中间件。 由于尚未配置默认策略,因此单独的 app.UseCors() 不会启用 CORS。
  • /echo 和控制器终结点允许使用指定策略的跨源请求。
  • /echo2 和 Razor Pages 终结点不允许跨源请求,因为未指定默认策略。

[DisableCors] 属性不会禁用终结点路由已使用 RequireCors 启用的 CORS。

ASP.NET Core 7.0 中,[EnableCors] 属性必须传递参数,否则系统会根据路由上的不明确匹配生成 ASP0023 警告。 ASP.NET Core 8.0 及更高版本不会生成 ASP0023 警告。

C#

[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
    // OPTIONS: api/TodoItems2/5
    [HttpOptions("{id}")]
    public IActionResult PreflightRoute(int id)
    {
        return NoContent();
    }

    // OPTIONS: api/TodoItems2 
    [HttpOptions]
    public IActionResult PreflightRoute()
    {
        return NoContent();
    }

    [HttpPut("{id}")]
    public IActionResult PutTodoItem(int id)
    {
        if (id < 1)
        {
            return BadRequest();
        }

        return ControllerContext.MyDisplayRouteInfo(id);
    }

    // [EnableCors] // Not needed as OPTIONS path provided.
    [HttpDelete("{id}")]
    public IActionResult MyDelete(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);

    // [EnableCors] //  Warning ASP0023 Route '{id}' conflicts with another action route.
    //                  An HTTP request that matches multiple routes results in an ambiguous
    //                  match error.
    [EnableCors("MyPolicy")] // Required for this path.
    [HttpGet]
    public IActionResult GetTodoItems() =>
        ControllerContext.MyDisplayRouteInfo();

    [HttpGet("{action}")]
    public IActionResult GetTodoItems2() =>
        ControllerContext.MyDisplayRouteInfo();

    [EnableCors("MyPolicy")]  // Required for this path.
    [HttpDelete("{action}/{id}")]
    public IActionResult MyDelete2(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);
}

有关测试与前面代码类似的代码的说明,请参阅使用 [EnableCors] 属性和 RequireCors 方法测试 CORS

使用属性启用 CORS

使用 [EnableCors] 属性启用 CORS,并仅对需要 CORS 的终结点应用命名策略可提供最佳控制。

[EnableCors] 属性提供了全局应用 CORS 的替代方法。 [EnableCors] 属性为所选终结点(而不是所有终结点)启用 CORS:

  • [EnableCors] 指定默认策略。
  • [EnableCors("{Policy String}")] 指定命名策略。

[EnableCors] 属性可应用于:

  • Razor Page PageModel
  • 控制器
  • 控制器操作方法

可将不同的策略应用于具有 [EnableCors] 属性的控制器、页面模型或操作方法。 如果将 [EnableCors] 属性应用于控制器、页面模型或操作方法,并且在中间件中启用了 CORS,则会应用两种策略。 建议不要合并策略。 使用 [EnableCors]属性或中间件,两者不能位于同一应用中。

以下代码对每种方法应用不同的策略:

C#

[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
    // GET api/values
    [EnableCors("AnotherPolicy")]
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "green widget", "red widget" };
    }

    // GET api/values/5
    [EnableCors("Policy1")]
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        return id switch
        {
            1 => "green widget",
            2 => "red widget",
            _ => NotFound(),
        };
    }
}

以下代码创建两个 CORS 策略:

C#

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("Policy1",
        policy =>
        {
            policy.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });

    options.AddPolicy("AnotherPolicy",
        policy =>
        {
            policy.WithOrigins("http://www.contoso.com")
                                .AllowAnyHeader()
                                .AllowAnyMethod();
        });
});

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseRouting();

app.UseCors();

app.UseAuthorization();

app.MapControllers();

app.Run();

为了最精细地控制 CORS 请求的限制:

  • 将 [EnableCors("MyPolicy")] 与命名策略一起使用。
  • 不要定义默认策略。
  • 不要使用终结点路由

下一部分中的代码符合前面的列表。

有关测试与前面代码类似的代码的说明,请参阅测试 CORS

禁用 CORS

[DisableCors] 属性不会禁用终结点路由已启用的 CORS。

以下代码定义 CORS 策略 "MyPolicy"

C#

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: "MyPolicy",
        policy =>
        {
            policy.WithOrigins("http://example.com",
                                "http://www.contoso.com")
                    .WithMethods("PUT", "DELETE", "GET");
        });
});

builder.Services.AddControllers();
builder.Services.AddRazorPages();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors();

app.UseAuthorization();

app.UseEndpoints(endpoints => {
    endpoints.MapControllers();
    endpoints.MapRazorPages();
});

app.Run();

以下代码为 GetValues2 操作禁用 CORS:

C#

[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public IActionResult Get() =>
        ControllerContext.MyDisplayRouteInfo();

    // GET api/values/5
    [HttpGet("{id}")]
    public IActionResult Get(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);

    // PUT api/values/5
    [HttpPut("{id}")]
    public IActionResult Put(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);


    // GET: api/values/GetValues2
    [DisableCors]
    [HttpGet("{action}")]
    public IActionResult GetValues2() =>
        ControllerContext.MyDisplayRouteInfo();

}

前面的代码:

有关测试前面代码的说明,请参阅测试 CORS

CORS 策略选项

本部分介绍可以在 CORS 策略中设置的各种选项:

AddPolicy 在 Program.cs 中调用。 对于某些选项,先阅读 CORS 的工作原理部分可能会有所帮助。

设置允许的源

AllowAnyOrigin:允许具有任何方案(http 或 https)的所有源的 CORS 请求。 AllowAnyOrigin 不安全,因为任何网站都可以向应用发出跨源请求。

 备注

指定 AllowAnyOrigin,且 AllowCredentials 是不安全的配置,可能会导致跨站点请求伪造。 当应用使用这两种方法进行配置时,CORS 服务将返回无效的 CORS 响应。

AllowAnyOrigin 影响预检请求和 Access-Control-Allow-Origin 头。 有关详细信息,请参阅预检请求部分。

SetIsOriginAllowedToAllowWildcardSubdomains:将策略的 IsOriginAllowed 属性设置为一个函数,当计算是否允许源时,此函数允许源匹配已配置的通配符域。

C#

var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
        policy =>
        {
            policy.WithOrigins("https://*.example.com")
                .SetIsOriginAllowedToAllowWildcardSubdomains();
        });
});

builder.Services.AddControllers();

var app = builder.Build();

设置允许的 HTTP 方法

AllowAnyMethod

  • 允许任何 HTTP 方法:
  • 影响预检请求和 Access-Control-Allow-Methods 头。 有关详细信息,请参阅预检请求部分。

设置允许的请求头

要允许在称为作者请求头的 CORS 请求中发送特定头,请调用 WithHeaders 并指定允许的头:

C#

using Microsoft.Net.Http.Headers;

var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
       policy =>
       {
           policy.WithOrigins("http://example.com")
                  .WithHeaders(HeaderNames.ContentType, "x-custom-header");
       });
});

builder.Services.AddControllers();

var app = builder.Build();

要允许所有 作者请求头,请调用 AllowAnyHeader

C#

var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
        policy =>
        {
            policy.WithOrigins("https://*.example.com")
                   .AllowAnyHeader();
        });
});

builder.Services.AddControllers();

var app = builder.Build();

AllowAnyHeader 影响预检请求和 Access-Control-Request-Headers 头。 有关详细信息,请参阅预检请求部分。

仅当在 Access-Control-Request-Headers 中发送的头与 WithHeaders 中所述的头完全匹配时,才能与 WithHeaders 指定的特定头匹配 CORS 中间件策略。

例如,考虑按如下方式配置的应用:

C#

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));

CORS 中间件拒绝具有以下请求头的预检请求,因为 Content-Language (HeaderNames.ContentLanguage) 未列在 WithHeaders 中:

Access-Control-Request-Headers: Cache-Control, Content-Language

应用返回 200 OK 响应,但不发回 CORS 头。 因此,浏览器不会尝试跨源请求。

设置公开的响应头

默认情况下,浏览器不会向应用公开所有响应头。 有关详细信息,请参阅 W3C 跨源资源共享(术语):简单响应头

默认情况下可用的响应头包括:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS 规范将这些头称为简单响应头。 要使其他头可用于应用,请调用 WithExposedHeaders

C#

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("MyExposeResponseHeadersPolicy",
        policy =>
        {
            policy.WithOrigins("https://*.example.com")
                   .WithExposedHeaders("x-custom-header");
        });
});

builder.Services.AddControllers();

var app = builder.Build();

跨源请求中的凭据

凭据需要在 CORS 请求中进行特殊处理。 默认情况下,浏览器不会使用跨源域请求发送凭据。 凭据包括 cookie 和 HTTP 身份验证方案。 要使用跨源请求发送凭据,客户端必须将 XMLHttpRequest.withCredentials 设置为 true

直接使用 XMLHttpRequest

JavaScript

var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;

使用 JQuery

JavaScript

$.ajax({
  type: 'get',
  url: 'https://www.example.com/api/test',
  xhrFields: {
    withCredentials: true
  }
});

使用 Fetch API

JavaScript

fetch('https://www.example.com/api/test', {
    credentials: 'include'
});

服务器必须允许凭据。 要允许跨源凭据,请调用 AllowCredentials

C#

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("MyMyAllowCredentialsPolicy",
        policy =>
        {
            policy.WithOrigins("http://example.com")
                   .AllowCredentials();
        });
});

builder.Services.AddControllers();

var app = builder.Build();

HTTP 响应包含一个 Access-Control-Allow-Credentials 头,它告诉浏览器服务器允许跨源请求的凭据。

如果浏览器发送凭据,但响应不包含有效的 Access-Control-Allow-Credentials 头,则浏览器不会向应用公开响应,而且跨源请求会失败。

允许跨源凭据会带来安全风险。 另一个域中的网站可以在用户不知情的情况下代表用户将登录用户的凭据发送到应用。

CORS 规范还指出,如果存在 Access-Control-Allow-Credentials 头,则将源设置为 "*"(所有源)是无效的。

预检请求

对于某些 CORS 请求,浏览器会在发出实际请求之前发送额外的 OPTIONS 请求。 此请求称为预检请求。 如果满足以下所有条件,浏览器可以跳过预检请求:

  • 请求方法为 GET、HEAD 或 POST。
  • 应用不会设置 AcceptAccept-LanguageContent-LanguageContent-Type 或 Last-Event-ID 以外的请求头。
  • Content-Type 头(如果已设置)具有以下值之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

为客户端请求设置的请求头规则适用于应用通过在 XMLHttpRequest 对象上调用 setRequestHeader 设置的头。 CORS 规范将这些头称为作者请求头。 此规则不适用于浏览器可以设置的头,如 User-AgentHost 或 Content-Length

以下是与本文档测试 CORS 部分中的 [Put test] 按钮发出的预检请求类似的示例响应。

General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content

Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin

Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0

预检请求使用 HTTP OPTIONS 方法。 它可能包含以下头:

如果预检请求被拒绝,应用将返回 200 OK 响应,但不会设置 CORS 头。 因此,浏览器不会尝试跨源请求。 有关被拒绝的预检请求的示例,请参阅本文档的测试 CORS 部分。

使用 F12 工具时,控制台应用会显示类似于以下内容之一的错误,具体取决于浏览器:

  • Firefox:跨源请求被阻止:同源策略不允许读取 https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 上的远程资源。 (原因:CORS 请求不成功)。 了解详细信息
  • 基于 Chromium:从源“https://cors3.azurewebsites.net”中的“https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5”提取的访问已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在 Access-Control-Allow-Origin 头。 如果不透明响应满足你的需求,请将请求的模式设置为“no-cors”以提取禁用 CORS 的资源。

要允许特定的头,请调用 WithHeaders

C#

using Microsoft.Net.Http.Headers;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("MyAllowHeadersPolicy",
        policy =>
        {
        policy.WithOrigins("http://example.com")
                   .WithHeaders(HeaderNames.ContentType, "x-custom-header");
        });
});

builder.Services.AddControllers();

var app = builder.Build();

要允许所有 作者请求头,请调用 AllowAnyHeader

C#

using Microsoft.Net.Http.Headers;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("MyAllowAllHeadersPolicy",
        policy =>
        {
            policy.WithOrigins("https://*.example.com")
                   .AllowAnyHeader();
        });
});

builder.Services.AddControllers();

var app = builder.Build();

浏览器设置 Access-Control-Request-Headers 的方式不一致。 如果:

  • 头设置为 "*" 以外的任何内容
  • 调用 AllowAnyHeader:至少包括 AcceptContent-Type 和 Origin,以及你想要支持的任何自定义头。

自动预检请求代码

通过以下方式应用 CORS 策略时:

  • 通过在 Program.cs 中调用 app.UseCors 在全局范围内应用。
  • 使用 [EnableCors] 属性。

ASP.NET Core 响应预检 OPTIONS 请求。

本文档的测试 CORS 部分演示了这种行为。

用于预检请求的 [HttpOptions] 属性

当使用适当的策略启用 CORS 时,ASP.NET Core 通常会自动响应 CORS 预检请求。

以下代码使用 [HttpOptions] 属性为 OPTIONS 请求创建终结点:

C#

[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
    // OPTIONS: api/TodoItems2/5
    [HttpOptions("{id}")]
    public IActionResult PreflightRoute(int id)
    {
        return NoContent();
    }

    // OPTIONS: api/TodoItems2 
    [HttpOptions]
    public IActionResult PreflightRoute()
    {
        return NoContent();
    }

    [HttpPut("{id}")]
    public IActionResult PutTodoItem(int id)
    {
        if (id < 1)
        {
            return BadRequest();
        }

        return ControllerContext.MyDisplayRouteInfo(id);
    }

有关测试上述代码的说明,请参阅使用 [EnableCors] 属性和 RequireCors 方法测试 CORS

设置预检过期时间

Access-Control-Max-Age 头指定对预检请求的响应可以缓存多长时间。 要设置此头,请调用 SetPreflightMaxAge

C#

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("MySetPreflightExpirationPolicy",
        policy =>
        {
            policy.WithOrigins("http://example.com")
                   .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
        });
});

builder.Services.AddControllers();

var app = builder.Build();

在终结点上启用 CORS

CORS 的工作原理

本节介绍 HTTP 消息级别的 CORS 请求中发生的情况。

  • CORS 不是一项安全功能。 CORS 是一种 W3C 标准,允许服务器放宽同源策略。
    • 例如,恶意行为者可能对你的网站使用跨站脚本 (XSS),并向其启用了 CORS 的网站执行跨站请求以窃取信息。
  • 允许 CORS 并不会使 API 更安全。
    • 由客户端(浏览器)执行 CORS。 服务器执行请求并返回响应,客户端返回错误并阻止响应。 例如,以下任何工具都会显示服务器响应:
  • 通过这种方式,服务器允许浏览器执行跨源 XHR 或 Fetch API 请求,否则会被禁止。
    • 没有 CORS 的浏览器无法执行跨源请求。 在 CORS 之前,使用 JSONP 来规避此限制。 JSONP 不使用 XHR,它使用 <script> 标记来接收响应。 允许跨源加载脚本。

CORS 规范介绍了几个新的 HTTP 标头,它们支持跨源请求。 如果浏览器支持 CORS,则会自动为跨源请求设置这些头。 启用 CORS 不需要自定义 JavaScript 代码。

已部署示例上的 PUT test 按钮

以下是从 Values 测试按钮到 https://cors1.azurewebsites.net/api/values 的跨源请求示例。 Origin 头:

  • 提供发出请求的网站的域。
  • 是必需项,并且必须与主机不同。

通用头

Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK

响应头

Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET

请求标头

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...

在 OPTIONS 请求中,服务器在响应中设置 Access-Control-Allow-Origin: {allowed origin} 响应头。 例如,已部署示例Delete [EnableCors] 按钮 OPTIONS 请求包含以下头:

通用头

Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content

响应头

Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET

请求标头

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0

在前面的响应头中,服务器在响应中设置了 Access-Control-Allow-Origin 头。 此头的 https://cors1.azurewebsites.net 值与请求中的 Origin 头一致。

如果调用 AllowAnyOrigin,则返回通配符值 Access-Control-Allow-Origin: *。 AllowAnyOrigin 允许任何源。

如果响应不包含 Access-Control-Allow-Origin 头,则跨源请求失败。 具体来说,浏览器不允许该请求。 即使服务器返回成功的响应,浏览器也不会将响应提供给客户端应用。

HTTP 重定向到 HTTPS 会导致 CORS 预检请求出现 ERR_INVALID_REDIRECT

UseHttpsRedirection 使用 HTTP(但重定向到 HTTPS)对终结点进行的请求失败,并返回 ERR_INVALID_REDIRECT on the CORS preflight request

API 项目可以拒绝 HTTP 请求,而不是使用 UseHttpsRedirection 将请求重定向到 HTTPS。

IIS 中的 CORS

部署到 IIS 时,如果服务器未配置为允许匿名访问,则 CORS 必须在 Windows 身份验证之前运行。 要支持此方案,需要为应用安装和配置 IIS CORS 模块

测试 CORS

示例下载包含测试 CORS 的代码。 请参阅如何下载。 该示例是一个 API 项目,其中添加了 Razor Pages:

C#

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: "MyPolicy",
        policy =>
        {
            policy.WithOrigins("http://example.com",
                    "http://www.contoso.com",
                    "https://cors1.azurewebsites.net",
                    "https://cors3.azurewebsites.net",
                    "https://localhost:44398",
                    "https://localhost:5001")
                .WithMethods("PUT", "DELETE", "GET");
        });
});

builder.Services.AddControllers();
builder.Services.AddRazorPages();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors();

app.UseAuthorization();

app.MapControllers();
app.MapRazorPages();

app.Run();

 警告

WithOrigins("https://localhost:<port>"); 应仅用于测试类似于下载示例代码的示例代码。

以下 ValuesController 提供了用于测试的终结点:

C#

[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public IActionResult Get() =>
        ControllerContext.MyDisplayRouteInfo();

    // GET api/values/5
    [HttpGet("{id}")]
    public IActionResult Get(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);

    // PUT api/values/5
    [HttpPut("{id}")]
    public IActionResult Put(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);


    // GET: api/values/GetValues2
    [DisableCors]
    [HttpGet("{action}")]
    public IActionResult GetValues2() =>
        ControllerContext.MyDisplayRouteInfo();

}

MyDisplayRouteInfo 由 Rick.Docs.Samples.RouteInfo NuGet 包提供,会显示路由信息。

使用以下方法之一测试上述示例代码:

  • 使用 https://cors3.azurewebsites.net/ 上部署的示例应用。 无需下载示例。
  • 使用 https://localhost:5001 的默认 URL 运行带有 dotnet run 的示例。
  • 从 Visual Studio 运行示例,并针对 https://localhost:44398 的 URL 将端口设置为 44398。

使用带有 F12 工具的浏览器:

  • 选择“值”按钮并在“网络”选项卡中查看头。
  • 选择“PUT test”按钮。 有关显示 OPTIONS 请求的说明,请参阅显示 OPTIONS 请求。 PUT test 会创建两个请求,一个 OPTIONS 预检请求和一个 PUT 请求。
  • 选择此 GetValues2 [DisableCors] 按钮可触发失败的 CORS 请求。 如文档中所述,响应返回 200 成功,但没有发出 CORS 请求。 选择“控制台”选项卡可查看 CORS 错误。 根据浏览器的不同,将显示类似于以下内容的错误:

    从源 'https://cors3.azurewebsites.net' 中的 'https://cors1.azurewebsites.net/api/values/GetValues2' 提取的访问已被 CORS 策略阻止:请求的资源上不存在 Access-Control-Allow-Origin 头。 如果不透明响应满足你的需求,请将请求的模式设置为“no-cors”以提取禁用 CORS 的资源。

启用了 CORS 的终结点可以使用 curlFiddler 或 Postman 等工具进行测试。 使用工具时,Origin 头指定的请求源必须与接收请求的主机不同。 如果根据 Origin 头的值,请求未跨源,则:

  • 无需 CORS 中间件来处理请求。
  • 不会在响应中返回 CORS 头。

以下命令使用 curl 发出包含信息的 OPTIONS 请求:

Bash

curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i

使用 [EnableCors] 属性和 RequireCors 方法测试 CORS

请考虑以下代码,该代码使用终结点路由,通过 RequireCors 按终结点启用 CORS:

C#

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: "MyPolicy",
        policy =>
        {
            policy.WithOrigins("http://example.com",
                    "http://www.contoso.com",
                    "https://cors1.azurewebsites.net",
                    "https://cors3.azurewebsites.net",
                    "https://localhost:44398",
                    "https://localhost:5001")
                .WithMethods("PUT", "DELETE", "GET");
        });
});

builder.Services.AddControllers();
builder.Services.AddRazorPages();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/echo",
        context => context.Response.WriteAsync("echo"))
        .RequireCors("MyPolicy");

    endpoints.MapControllers();
    endpoints.MapRazorPages();
});

app.Run();

请注意,只有 /echo 终结点使用 RequireCors 来允许使用指定策略的跨域请求。 下面的控制器使用 [EnableCors] 属性来启用 CORS。

以下 TodoItems1Controller 提供了用于测试的终结点:

C#

[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase 
{
    // PUT: api/TodoItems1/5
    [HttpPut("{id}")]
    public IActionResult PutTodoItem(int id) {
        if (id < 1) {
            return Content($"ID = {id}");
        }

        return ControllerContext.MyDisplayRouteInfo(id);
    }

    // Delete: api/TodoItems1/5
    [HttpDelete("{id}")]
    public IActionResult MyDelete(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);

    // GET: api/TodoItems1
    [HttpGet]
    public IActionResult GetTodoItems() =>
        ControllerContext.MyDisplayRouteInfo();

    [EnableCors("MyPolicy")]
    [HttpGet("{action}")]
    public IActionResult GetTodoItems2() =>
        ControllerContext.MyDisplayRouteInfo();

    // Delete: api/TodoItems1/MyDelete2/5
    [EnableCors("MyPolicy")]
    [HttpDelete("{action}/{id}")]
    public IActionResult MyDelete2(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);
}

从已部署示例测试页测试前面的代码。

Delete [EnableCors] 和 GET [EnableCors] 按钮成功,因为终结点具有 [EnableCors] 并会响应预检请求。 其他终结点失败。 GET 按钮失败,因为 JavaScript 发送:

JavaScript

 headers: {
      "Content-Type": "x-custom-header"
 },

以下 TodoItems2Controller 提供了类似的终结点,但包含响应 OPTIONS 请求的显式代码:

C#

[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
    // OPTIONS: api/TodoItems2/5
    [HttpOptions("{id}")]
    public IActionResult PreflightRoute(int id)
    {
        return NoContent();
    }

    // OPTIONS: api/TodoItems2 
    [HttpOptions]
    public IActionResult PreflightRoute()
    {
        return NoContent();
    }

    [HttpPut("{id}")]
    public IActionResult PutTodoItem(int id)
    {
        if (id < 1)
        {
            return BadRequest();
        }

        return ControllerContext.MyDisplayRouteInfo(id);
    }

    // [EnableCors] // Not needed as OPTIONS path provided.
    [HttpDelete("{id}")]
    public IActionResult MyDelete(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);

    // [EnableCors] //  Warning ASP0023 Route '{id}' conflicts with another action route.
    //                  An HTTP request that matches multiple routes results in an ambiguous
    //                  match error.
    [EnableCors("MyPolicy")] // Required for this path.
    [HttpGet]
    public IActionResult GetTodoItems() =>
        ControllerContext.MyDisplayRouteInfo();

    [HttpGet("{action}")]
    public IActionResult GetTodoItems2() =>
        ControllerContext.MyDisplayRouteInfo();

    [EnableCors("MyPolicy")]  // Required for this path.
    [HttpDelete("{action}/{id}")]
    public IActionResult MyDelete2(int id) =>
        ControllerContext.MyDisplayRouteInfo(id);
}

从已部署示例的测试页测试前面的代码。 在“控制器”下拉列表中,选择“预检”,然后选择“设置控制器”。 对 TodoItems2Controller 终结点的所有 CORS 调用都成功。

.net core实现跨域 - .NET开发菜鸟 - 博客园

mikel阅读(334)

 

来源: .net core实现跨域 – .NET开发菜鸟 – 博客园

什么是跨域在前面已经讲解过了,这里便不再讲解,直接上代码。

一、后台API接口

用.net core创建一个Web API项目负责给前端界面提供数据。

二、前端界面

建立两个MVC项目,模拟不同的ip,在view里面添加按钮调用WEB API提供的接口进行测试跨域。view视图页代码如下:

复制代码
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>跨域测试1</title>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script>
        function btnGet() {
            $.ajax({
                url: 'https://localhost:44355/api/values',
                type: "Get",
                dataType: "json",
                success: function (data) {
                    alert("成功");
                },
                error: function (data) {
                    alert("失败");
                }
            });
        }
    </script>
</head>
<body>
    <div> 
        <input type="button" id="btn" value="测试跨域" onclick="btnGet()" />
    </div>
</body>
</html>
复制代码

三、测试

1、不设置允许跨域

首先,先不设置.net core允许跨域,查看调用效果:

点击测试跨域1按钮:

F12进入Debug模式查看失败原因:

从这里可以看出来是因为产生了跨域问题,所以会失败。

点击测试跨域2的效果和此效果一致。

2、设置允许所有来源跨域

2.1、在StartUp类的ConfigureServices方法中添加如下代码:

// 配置跨域处理,允许所有来源
services.AddCors(options =>
options.AddPolicy("cors",
p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials()));

2.2、修改Configure方法

// 允许所有跨域,cors是在ConfigureServices方法中配置的跨域策略名称
app.UseCors("cors");

2.3、测试

 

从截图中可以看出,这次调用成功了。

3、设置特定来源可以跨域

3.1、修改ConfigureServices方法代码如下:

复制代码
//允许一个或多个来源可以跨域
services.AddCors(options =>
{
      options.AddPolicy("CustomCorsPolicy", policy =>
      {
             // 设定允许跨域的来源,有多个可以用','隔开
             policy.WithOrigins("http://localhost:21632")
             .AllowAnyHeader()
             .AllowAnyMethod()
             .AllowCredentials();
      });
});
复制代码

这里设置只允许ip为http://localhost:21632的来源允许跨域。

3.2、修改Configure代码如下:

// 设定特定ip允许跨域 CustomCorsPolicy是在ConfigureServices方法中配置的跨域策略名称
app.UseCors("CustomCorsPolicy");

3.3测试

点击跨域测试1按钮,结果如下:

可以看到访问成功了,然后在点击跨域测试2按钮,结果如下:

发现这次访问失败了,F12进入Debug模式,查看失败原因:

从截图中可以看出是因为这里产生了跨域请求,但是没有允许跨域测试2所在的ip跨域。那么如果也想让跨域测试2可以调用成功该怎么办呢?

光标定位到WithOrigins上面,然后F12查看定义:

从截图中发现:WithOrigins的参数是一个params类型的字符串数组,如果要允许多个来源可以跨域,只要传一个字符串数组就可以了,所以代码修改如下:

复制代码
//允许一个或多个来源可以跨域
services.AddCors(options =>
{
      options.AddPolicy("CustomCorsPolicy", policy =>
      {
            // 设定允许跨域的来源,有多个可以用','隔开
            policy.WithOrigins("http://localhost:21632", "http://localhost:24661")
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowCredentials();
      });
});
复制代码

这时跨域测试2也可以调用成功了

4、优化

在上面的例子中,需要分两步进行设置才可以允许跨域,有没有一种方法只需要设置一次就可以呢?在Configure方法中只设置一次即可,代码如下:

复制代码
// 设置允许所有来源跨域
app.UseCors(options =>
{
       options.AllowAnyHeader();
       options.AllowAnyMethod();
       options.AllowAnyOrigin();
       options.AllowCredentials();
});

// 设置只允许特定来源可以跨域
app.UseCors(options =>
{
        options.WithOrigins("http://localhost:3000", "http://127.0.0.1"); // 允许特定ip跨域
        options.AllowAnyHeader();
        options.AllowAnyMethod();
        options.AllowCredentials();
});
复制代码

5、利用配置文件实现跨域

在上面的示例中,都是直接把ip写在了程序里面,如果要增加或者修改允许跨域的ip就要修改代码,这样非常不方便,那么能不能利用配置文件实现呢?看下面的例子。

5.1、修改appsettings.json文件如下:

复制代码
{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": {
    "url": "http://localhost:21632|http://localhost:24663"
  }
}
复制代码

AllowedHosts里面设置的是允许跨域的ip,多个ip直接用“|”进行拼接,也可以用其他符合进行拼接。

5.2、增加CorsOptions实体类

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CorsDomainDemo
{
    public class CorsOptions
    {
        public string url { get; set; }
    }
}
复制代码

 

5.3、 新增OptionConfigure方法

private void OptionConfigure(IServiceCollection services)
{
    services.Configure<CorsOptions>(Configuration.GetSection("AllowedHosts"));
}

 

5.4、在ConfigureServices方法里面调用OptionConfigure方法

// 读取配置文件内容
OptionConfigure(services);

 

5.5、修改Configure方法,增加IOptions<CorsOptions>类型的参数,最终代码如下

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace CorsDomainDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // 配置跨域处理,允许所有来源
            //services.AddCors(options =>
            //options.AddPolicy("cors",
            //p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials()));

            //允许一个或多个来源可以跨域
            //services.AddCors(options =>
            //{
            //    options.AddPolicy("CustomCorsPolicy", policy =>
            //    {
            //        // 设定允许跨域的来源,有多个可以用','隔开
            //        policy.WithOrigins("http://localhost:21632", "http://localhost:24661")
            //          .AllowAnyHeader()
            //           .AllowAnyMethod()
            //           .AllowCredentials();
            //    });
            //});

            // 读取配置文件内容
            OptionConfigure(services);
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<CorsOptions> corsOptions)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            // 允许所有跨域,cors是在ConfigureServices方法中配置的跨域策略名称
            //app.UseCors("cors");

            // 设定特定ip允许跨域 CustomCorsPolicy是在ConfigureServices方法中配置的跨域策略名称
            //app.UseCors("CustomCorsPolicy");

            // 设置允许所有来源跨域
            //app.UseCors(options =>
            //{
            //    options.AllowAnyHeader();
            //    options.AllowAnyMethod();
            //    options.AllowAnyOrigin();
            //    options.AllowCredentials();
            //});

            // 设置只允许特定来源可以跨域
            //app.UseCors(options =>
            //{
            //    options.WithOrigins("http://localhost:3000", "http://127.0.0.1"); // 允许特定ip跨域
            //    options.AllowAnyHeader();
            //    options.AllowAnyMethod();
            //    options.AllowCredentials();
            //});

            // 利用配置文件实现
            CorsOptions _corsOption = corsOptions.Value;
            // 分割成字符串数组
            string[] hosts = _corsOption.url.Split('|');

            // 设置跨域
            app.UseCors(options =>
            {
                options.WithOrigins(hosts);
                options.AllowAnyHeader();
                options.AllowAnyMethod();
                options.AllowCredentials();
            });

            app.UseHttpsRedirection();
            app.UseMvc();
        }

        private void OptionConfigure(IServiceCollection services)
        {
            services.Configure<CorsOptions>(Configuration.GetSection("AllowedHosts"));
        }
    }
}
复制代码

 

这样就可以实现利用配置文件实现允许跨域了。

ASP.NET Core WebApi配置跨域_asp.net core webapi 跨域-CSDN博客

mikel阅读(375)

来源: ASP.NET Core WebApi配置跨域_asp.net core webapi 跨域-CSDN博客

引言
一、开启跨域访问
二、配置跨域规则
二、远程跨域访问
引言
当我们在项目的额开发过程中,使用到前后端分离,而不再是传统的MVC进行开发时,我们的WebApi项目默认是没有开启跨域的,因为浏览器安全性可防止网页默认同域策略。 同域策略可防止恶意站点从另一站点读取敏感数据。 有时,你可能想要允许其他站点对你的应用进行跨域请求。

一、开启跨域访问
这里只需要注意一下:必须将对的调用 UseCors 置于 UseAuthorization之前 ,UseRouting 之后

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseRouting();

//启用跨域
app.UseCors();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
二、配置跨域规则
public void ConfigureServices(IServiceCollection services)
{
//配置跨域
services.AddCors(options =>
{
options.AddPolicy(“CorsPolicy”, builder =>
{
builder.AllowAnyOrigin() //允许所有Origin策略

//允许所有请求方法:Get,Post,Put,Delete
.AllowAnyMethod()

//允许所有请求头:application/json
.AllowAnyHeader();
});
});
services.AddControllers();
}

二、远程跨域访问
[Route(“api/[controller]”)]
[ApiController]
[EnableCors(“CorsPolicy”)] //允许跨域
public class ValuesController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { “values1”, “values2” };
}
}

————————————————
版权声明:本文为CSDN博主「qq_42799562」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42799562/article/details/115447589

关于使用NewtonSoft.Json库反序列化遭遇Unexpected character的解决记录-CSDN博客

mikel阅读(818)

来源: 关于使用NewtonSoft.Json库反序列化遭遇Unexpected character的解决记录-CSDN博客

关于使用NewtonSoft.Json库反序列化遭遇Unexpected character的解决记录
环境
Unity版本:2021.3.27f1c2
NewtonSoft.Json库:从Unity Package Manager安装
问题描述
为了保存部分设置信息,我选择使用Json序列化保存,在使用时再反序列化读取的方式。
序列化时一切正常,但当我尝试反序列化时,报出了以下错误(仅展示最后几层调用栈):
JsonReaderException: Unexpected character encountered while parsing value: {. Path ‘BPMList[0].Beat’, line 1, position 66.
Newtonsoft.Json.JsonTextReader.ReadNumberValue (Newtonsoft.Json.ReadType readType) (at <761cf2a144514d2291a678c334d49e9b>:0)
Newtonsoft.Json.JsonTextReader.ReadAsInt32 () (at <761cf2a144514d2291a678c334d49e9b>:0)
Newtonsoft.Json.JsonReader.ReadForType (Newtonsoft.Json.Serialization.JsonContract contract, System.Boolean hasConverter) (at <761cf2a144514d2291a678c334d49e9b>:0)
寻找解决方案
寻找同类遭遇
首先就是通过搜索尝试找到有同样报错的人来找到解决方案,并且也确实找到了几个,且解决方案相同,下面贴上几个:
C#解析json报错Unexpected character encountered while parsing value: . Path ‘‘, line 0, position 0.
Newtonsoft.Json Unexpected character encountered while parsing value: .Path ‘’
这两个均是因为UTF-8-BOM的BOM头产生的问题,并以此解决了。
下面还有一个并非此问题但也有提到BOM头的情况
What does this JsonReaderException mean?
至少这说明BOM头确实会导致这样的异常发生,因此我也进行了尝试,但却得到了同样的报错:
可以看到,BOM头的三个字节(EF、BB、BF)均被移除了,但仍然存在该问题,这也就说明我遇到的异常并不是BOM引起的。
另寻思路
既然他人的方法行不通,我就只能自己尝试找到解决方法。
注意到该报错的调用栈顺序是:
ReadForType
ReadAsInt32
ReadNumberValue
而我的Json内容是:
{
“Name”:”test”,
“MusicName”:”audio”,
“BPMList”:[
{
“BPM”:60.0,
“Beat”:{
“Beat”:1,
“UpPart”:1,
“DownPart”:4
}
}
],
“MusicExt”:”.ogg”
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
因此我认为是反序列化时错误的将外部的Beat当作int处理了。
但当我尝试自定义序列化/反序列化(继承JsonConverter并重写)时,却发现不起作用。
找到问题
正当我一筹莫展时,突然注意到我的Json内容中,有两个同样的变量名Beat,而报错中明确的说“ReadAsInt32”。
或许… …JsonCoverter将Object的Beat错当成下面的int的Beat了?
于是我将上面的Beat改为BeatInfo,重新进行了序列化和反序列化测试,结果如下:
可以看到没有报错,反序列化顺利完成!
结论
我不知道这属于是Json通病还是NewtonSoft.Json的问题,至少在我的这次经历中确实表现出了这样的bug:当多个字段的名称相同而类型不同时,会用错误的类型对同名字段进行反序列化,从而触发JsonReaderException: Unexpected character encountered while parsing value的异常
挺少见的一个bug,所以我在此做一下记录,也希望能对遇到同样问题的人有所帮助吧。
————————————————
版权声明:本文为CSDN博主「SlipperSoar」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/SlipperSoar/article/details/132154474

axios四种方式GET/POST/DELETE/PUT的参数传递_put请求参数写在params里吗-CSDN博客

mikel阅读(343)

来源: axios四种方式GET/POST/DELETE/PUT的参数传递_put请求参数写在params里吗-CSDN博客

 

看一个最简单的例子:

app.get(‘/adata’, (req, res) => {
res.send(‘hello axios!’)
})axios.get(‘http://localhost:9999/adata’).then((response)=>{
console.log(response.data)
})
结果:

注意这里的data是固定的
如果我们只看返回的response:

 

axios参数传递-GET传递参数

传统查询字符串方式传参
app.get(‘/axios’, (req, res) => {
res.send(‘axios GET传递参数:’ + req.query.id)
})
axios.get(‘http://localhost:9999/axios?id=1000’).then((response) => {
console.log(response)
})
注意,这里因为是查询字符串?id=1000,所以服务端用req.query

结果

restful风格URL传参
<script>
axios.get(‘http://localhost:9999/axios/1000’).then((response) => {
console.log(response)
})
</script>
app.get(‘/axios/:id’, (req, res) => {
res.send(‘axios GET(RESTFUL)传递参数:’ + req.params.id)
})
注意这里因为不是查询字符串,而是restful传参,所以服务端需要:id来接收一下,并且后面只能用req.params.id来得到参数
结果:

用axios自带的params选项传参(这个其实就是查询字符串的另一种形式只不过参数不写在url里而是写在params对象里):
axios.get(‘http://localhost:9999/axios’, {
params: {
id: 5678,
info: ‘data within params’
}
}).then((result) => {
console.log(result.data)
})
// 因为还是get请求,所以走的还是这个路由
// 参数写在params里面还是查询字符串,所以服务端用req.query接收
app.get(‘/axios’, (req, res) => {
console.log(JSON.stringify(req.query))
res.send(‘axios GET传递参数:’ + JSON.stringify(req.query))
})

结果:

 

 

axios参数传递-DELETE传递参数

和上面get差不多,我们简单演示一下:

restful风格URL传参

 

传统查询字符串方式传参

查询字符串走的是这个路由:

结果:

 

3. params方式:

路由走的是这个:

结果:

 

axios参数传递-POST传递参数
默认传递参数

结果:

 

通过URLSearchParams传递参数

还是这个路由:

结果:

 

axios参数传递-PUT传递参数

看代码:

结果:

 

————————————————
版权声明:本文为CSDN博主「Akimoto Hiroshi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dyw3390199/article/details/111401089

[FromBody] JObject 接收数据 报错 The JSON value could not be converted to Newtonsoft.Json.Linq.JToken-CSDN博客

mikel阅读(356)

来源: [FromBody] JObject 接收数据 报错 The JSON value could not be converted to Newtonsoft.Json.Linq.JToken-CSDN博客

.net core WebApi 使用[FromBody] JObject 接收数据 报错

使用postman 测试

查找资料后发现需要引入包Microsoft.AspNetCore.Mvc.NewtonsoftJson

然后在 Startup.cs 的ConfigureServices方法中加入

services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});

重新生成再用postman测试 发现成功

如果需要用postman测试 需要注意把
Content-Type设为application/json
Body 选中raw 选择JSON
————————————————
版权声明:本文为CSDN博主「M鹿M」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43832558/article/details/109095730

Vue使用axios----ReferenceError: axios is not defined问题解决-CSDN博客

mikel阅读(310)

来源: Vue使用axios—-ReferenceError: axios is not defined问题解决-CSDN博客

问题1:ReferenceError: axios is not defined

问题代码:

const requrl = ‘/user/find/1’
axios.get(requrl).then(response => {
const user = response.data
this.username = user.username
this.age = user.age
}).catch(
function (error) {
// 请求失败处理
alert(‘请求失败!’)
})

解决方案1:
main.js加上Vue.prototype.$axios = axios
axios.get改为this.$axios.get调用,修改后不再报错

import axios from ‘axios’
//其他vue组件中就可以this.$axios调用使用
Vue.prototype.$axios = axios

const requrl = ‘/user/find/1’
this.$axios.get(requrl).then(response => {
const user = response.data
this.username = user.username
this.age = user.age
}).catch(
function (error) {
// 请求失败处理
alert(‘请求失败!’)
})

解决方案2:结合vue-axios插件,安装插件后,就不需要将axios绑定到Vue原型链上了,组件内通过this.axios调用
npm install axios vue-axios –save

import axios from ‘axios’
import VueAxios from “vue-axios”;
Vue.use(VueAxios,axios)
//其他vue组件中就可以this.$axios调用使用
//Vue.prototype.$axios = axios

const requrl = ‘/user/find/1’
this.axios.get(requrl).then(response => {
const user = response.data
this.username = user.username
this.age = user.age
}).catch(
function (error) {
// 请求失败处理
alert(‘请求失败!’)
})

问题2,并发测试时,TypeError: Cannot read property ‘$axios’ of undefined

报错代码如下:

function getUserget() {
return this.$axios.get(‘/user/find/1’)
}
function getUserpost() {
return this.$axios.post(‘/user/find’,{id:2})
}
this.$axios.all([getUserget(), getUserpost()])
.then(this.$axios.spread(function (res1, res2) {
// 两个请求现在都执行完成
const user1 = res1.data
const user2 = res2.data
console.log(user1.username)
console.log(user2.username)
}));

原因未知,有知道的大佬还望不吝赐教
无奈只得在app.vue(我是在这里做的测试)中再次引入
import axios from ‘axios’
再次引入,直接用axios就行

function getUserget() {
return axios.get(‘/user/find/1’);
}
function getUserpost() {
return axios.post(‘/user/find’,{id:2});
}

————————————————
版权声明:本文为CSDN博主「纷纷四季」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Laputa219/article/details/106802230

Vue入门项目——WebApi-CSDN博客

mikel阅读(389)

来源: Vue入门项目——WebApi-CSDN博客

Vue入门——WebApi
vue3项目搭建
组合式API
响应式API
reactive()
ref()
生命周期钩子
computed计算属性函数
watch监听函数
父子通信
模板引用
组合选项
vue3项目搭建
简单看下Vue3的优势吧

下载安装npm及node.js16.0以上版本(确保安装成功可用如下代码检查版本)

npm -v
node -v

下一步创建vue3项目,输入项目名字后并进行选择插件(可以直接回车全部no)

npm init vue@latest

然后找到项目用vsCode打开,并进行初始化

npm install

初始化完成后,把项目跑起来,可点击链接进行查看,看到如下画面就完成咯

npm run dev

组合式API
响应式API

reactive()
接收一个普通对象然后返回该普通对象的响应式代理(众所周知括号里的内容一般才是最重要的,没错,reactive只能封装对象类型的参数)
🍊个🌰:

<script setup>
//1、导入函数
import { reactive } from ‘vue’;
//2、执行函数,传入一个对象类型参数,用变量接收
const state = reactive({
count: 0 //参数是常规对象,不会引起视图更新
})
//使用reactive函数包装后,会变成响应式对象
const addCount = () => {
state.count++
}

const state2 = {
count2: 0 //参数是常规对象,不会引起视图更新
}
const addCount2 = () => {
state2.count2++
}
</script>
<template>
<div>
<button @click=”addCount” id=”btn1″>{{ state.count }}</button>
<!–这个按钮中的参数被reactive包裹,会被视图响应–>
<button @click=”addCount2″ id=”btn2″>{{state2.count2}}</button>
<!–这个参数没有被包裹不会响应–>
<!–但是会累积点击,在下一次点击第一个按钮时会被响应,一次性累计添加–>
</div>
</template>

ref()
接受一个参数值并返回一个响应式且可改变的 ref 对象。(找不同咯,对没错,ref()支持任何类型的参数对其进行封装)

<script setup>
//1、导入函数
import { ref } from ‘vue’;
//2、执行函数,传入一个参数(简单类型与对象类型均可),用变量接收
const count = ref(0)
const addCount = () => {
//脚本区域修改ref产生的响应式对象,必须通过.value属性修改
count.value++
}

const person = ref({
name: ‘芋头’
})
const setPerson = () => {
person.value.name = ‘一哑7’
}
</script>
<template>
<div>
<button @click=”addCount”>{{ count }}</button>
<!–点击button数字添加–>
</div>
<div>
<button @click=”setPerson”>{{ “这个人是” + person.name }}</button>
<!–点击button修改人名–>
</div>
</template>

冷知识:ref函数内部实现时依赖reactive函数,一般使用ref更多

生命周期钩子
先来看一张图熟悉一下api

详细的生命周期API使用请参考Vue3官网API介绍

生命周期函数:引入函数后执行并传入回调,会自动执行回调 多次执行生命周期函数时,回调会依次执行

<script setup>
//引入函数
import { onMounted } from ‘vue’

//执行函数并传入回调
onMounted( () => {
console.log(‘执行回调~’)
console.log(‘执行回调~’)
})

//多次执行函数时依次执行
onMounted( () => {
console.log(‘执行回调2~’)
console.log(‘执行回调2~’)
})

</script>

computed计算属性函数
<script setup>
//1、导入函数
import { ref , computed } from ‘vue’;
let list = ref([1 , 2 , 3 , 4 , 5 , 6 , 7 , 8])
//2、执行函数;return经过计算的值;用变量接受这个值
const computedList = computed(() => {
return list.value.filter(item => item > 2)
})
//计时器观察实时更新
setTimeout(() => {
list.value.push(-1 , 10 , 12 , 0)
} , 3000)
</script>
<template>
<div>
{{`原始数组是:[${list}]`}}
</div>
<div>
{{`新数组是:[${computedList}]`}}
</div>
</template>

watch监听函数
监听单个数据:
watch需要两个参数,第一个参数是需要监听的数据,第二个参数是在所需要监听的数据发生变化时所需要执行的回调函数。
<script setup>
//1、导入函数
import { ref , watch } from ‘vue’;
//2、设置需要监听的数据和回调函数
const count = ref(0)
const setCount = () => {
count.value++
}
//3、watch监听单个数据
watch(count , () => {
alert(‘哦豁,变了哦’)
})
</script>
<template>
<div>
<button @click=”setCount”>{{count}}</button>
</div>
</template>

监听多个数据:
这时只需要用数组把需要监听的数据封装起来就好了
<script setup>
//1、导入函数
import { ref , watch } from ‘vue’;
//2、设置需要监听的数据和回调函数
const count = ref(0)
const setCount = () => {
count.value++
}

const name = ref(‘芋头’)
const setName = () => {
name.value = ‘一哑7’
}
//3、watch监听多个数据,用数组把需要监听的数据封装起来就好了
watch([count , name] , ([newCount , newName] , [odlCount , oldName]) => {
alert(‘哦豁,变了哦’ + [odlCount , oldName] + ‘变成了’ + [newCount , newName] )
})
</script>
<template>
<div>
<button @click=”setCount”>{{count}}</button>
<button @click=”setName”>{{name}}</button>
</div>
</template>

不要忘了关于watch还有两个参数哦,immediate:立即执行;deep:深度监听

immediate : 在第一次刚刚监听到的时候就先执行一次
<script setup>
watch(count , () => {
alert(‘变了哦’)
} , {
immediate: true}
)
</script>

deep :通过watch监听的ref对象默认浅层监听,直接修改嵌套对象都不会出发回调函数,此时便需要开启deep
没理解?把下面代码复制下来删掉deep对比一下就知道咯
<script setup>
watch(name , () => {
alert(‘变了哦’)
} , {
deep: true
}
)
</script>

精确监听:监听多个属性中的一个属性(deep会有性能损耗建议不开启deep而是使用精确监听)
只需要把watch函数的参数变成两个回调函数,第一个是需要监听的东西,第二个是监听到之后需要执行的回调函数
🍊个🌰:

<script setup>
import { ref, watch } from ‘vue’
const state = ref({
name: ‘芋头’,
age: 22,
sex: ‘男’

})
const chanheName = () => {
//修改姓名
state.value.name = ‘一哑7’
}
const changeAge = () => {
//修改年龄~
state.value.age = 23
}
const changeSex = () => {
//去一趟泰国
state.value.sex = ‘女’
}
//精确侦听具体属性
watch(
() => state.value.age,
() => {
console.log(‘长大一岁了哦’)
}
)
watch(
() => state.value.name,
() => {
console.log(‘还顺路改了个名字’)
}
)
</script>
<template>
<div>
<div>这个人现在的名字:{{state.name}}</div>
<div>这个人现在的年龄:{{state.age}}</div>
</div>
<div>
<button @click=”chanheName”>修改姓名</button>
<button @click=”changeAge”>修改年领</button>
</div>
</template>

父子通信
父传子:在子组件中用defineProps接收父组件中绑定的数据就好了

//父亲页
<template>
<div>
I am dadTest
</div>
<div>
<sonTest />
</div>
<div>
父传子
<!– 父亲上绑定属性 –>
<sonTest message=”father Data” />
</div>
</template>
<script setup>
import sonTest from ‘./views/sonTest.vue’;
</script>

//儿子页
<template>
<div>
I am sonTest {{message}}
</div>
</template>
<script setup>
//用defineProps接收数据就好了
defineProps({
message: String
})
</script>

子传父:父组件通过@绑定事件,子组件内部通过defindEmits函数生成emit方法触发事件
defindEmits 传递参数是数组哦~,因为可传递所有绑定事件

//儿子页
<template>
<div>
<button @click=”sendMsg”>点击按钮查看来自子组件的信息</button>
</div>
</template>
<script setup>
//利用defindEmits函数生成emit方法
const emit = defineEmits([‘giveMeMessqge’])
const sendMsg = () => {
//出发绑定事件
emit(‘giveMeMessqge’ , ‘儿子消息’)
}
</script>

//父亲页
<template>
<div>
<sonTest @giveMeMessqge=”getMessage”/>
</div>
</template>
<script setup>
import sonTest from ‘./views/sonTest.vue’;
const getMessage = (msg) => {
alert(msg)
}
</script>

模板引用
默认情况下<script setup>语法糖下组件内部的属性与方法不对父组件开放,可以通过defineExpose编译宏指定哪些属性和方法允许访问

//子组件
<template>
<div>
Test 组件
</div>
</template>
<script setup>
import { ref } from ‘vue’;
const name = ref(‘nameTest’)
const setName = () => {
name.value = ‘newNameTest’
}

// defineExpose({
// name,
// setName
// })
</script>

//父组件
<template>
<div>
<!– 用ref标识绑定ref对象 –>
<h1 ref=”h1Ref”>dom标签h1</h1>
<sonTest ref=”sonRef”/>
</div>
</template>
<script setup>
import sonTest from ‘./views/sonTest.vue’;
import { ref , onMounted } from ‘vue’

//调用ref函数生成ref对象当然组件也是可以的
const h1Ref = ref(null)
const sonRef = ref(null)

//不过要注意在获取对象时要等组件挂在完毕哦,可以使用
onMounted(() => {
alert(h1Ref.value)
alert(sonRef.value)
})
</script>

组合选项
顶层组件向任意底层组件传递参数和方法,实现跨层组件通信顶层组件通过provide函数提供数据,底层组件通过inject函数获取数据

 

 

跨层传递普通数据:

 

跨层传递响应式数据:

 

跨层传递方法:顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件中的数据

 

————————————————
版权声明:本文为CSDN博主「一哑7」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45696320/article/details/131812520