如何使用“no-cors”将 JavaScript HTTP 发布请求代码更改为 C#?

Posted

技术标签:

【中文标题】如何使用“no-cors”将 JavaScript HTTP 发布请求代码更改为 C#?【英文标题】:How can I change JavaScript HTTP post request code to C#, using 'no-cors'? 【发布时间】:2021-02-12 15:09:54 【问题描述】:

我正在尝试做与在 javascript 代码中但在 C# 中所做的相同的事情。最终结果是我想从 C# 代码中自动执行此任务,我将在其中手动创建这些文件。此代码用于网页以实现其目标:

第一个函数是将文件放在缓冲区中的一个位置。

        function FileIOU(file: File, backendUrl: string, dispatch: any) 
            return new Promise((resolve, reject) => 
                const reader = new FileReader();
                reader.onerror = reject;
                reader.onload = async () => 
                    await fetch(`$ backendUrl/ www.FileIOU?filename =$file.name`, 
                        method: 'POST',
                        body: reader.result,
                        mode: 'no-cors',
                    ).then(resolve).catch (err => 
                        console.log('FileIOU', err);
                        dispatch(consoleOutputAction('Failed to send file: ' + file.name, 'error'));
                        reject();
                    );
                ;
         reader.readAsArrayBuffer(file);
        

第二个函数调用这个文件在站点上运行。

          fetch(`$props.configuration.backendUrl/www.RunFile?name=$e.currentTarget.id`); 
        

我模仿这个的方式是:

        public async static Task PostFile(string file)
    
        byte[] byteArray = new byte[]  ;
        File.WriteAllBytes(file, byteArray);
        var fileName = Path.GetFileName(file);
        var byteContent = new ByteArrayContent(byteArray);
        
        var response = await Client.PostAsync(
        "https://localhost/simulatorweb/www.FileIOU?filename="+$"fileName"
        , byteContent);
       
    

第二部分是:

    public async static Task RunFile(string fileName)
    
        var response = await Client.PostAsync(
            $"https://localhost/www.RunFile?name="+$"fileName", null);           
    

一旦我调用了这个函数,我就会得到响应405,尽管这可能看起来我需要根据 JavaScript 在 C# 中设置“no-cors”,尽管我不确定如何执行此操作。但可能还有其他问题,我没有看到。

StatusCode: 405, ReasonPhrase: 'Method Not Allowed', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:

  Date: Fri, 30 Oct 2020 06:15:42 GMT
  Connection: keep-alive
  Vary: Origin
  Accept-Ranges: bytes
  Content-Length: 0
  Allow: GET
  Allow: HEAD
  Allow: OPTIONS

【问题讨论】:

请注意:您当前正在向文件中写入 0 字节(使用File.WriteAllBytes),因为您初始化了一个空字节数组,因此您还将一个 0 字节的数组发布到您的服务器。你想要的是使用var byteArray = File.ReadAllBytes(file) CORS 是一项浏览器功能。 HttpClient 不使用也不遵守 CORS。 你的 JavaScript 版本中 backendUrl 的值是多少? 为什么要写文件? @MindSwipe 使用var byteArray = File.ReadAllBytes(file); 给了我完全相同的错误。我不能直接在Client.PostAsync 中使用它,因为它抱怨内容格式。 @John 好的,谢谢,所以据我了解,这不是 cors 问题。 【参考方案1】:

正如 John 在 cmets 中概述的那样,no-cors 不是您需要复制的服务器端事物。 CORS 是一种浏览器功能,如果 JavaScript 请求从 JavaScript 文件本身来源以外的地方下载内容,则浏览器(出于礼貌)检查目标服务器“对于您的 url x,JavaScript 可能在什么位置已从 x 下载并被允许访问 x?” - 这让服务器有机会响应“只有来自这些地方的 JavaScript 可以请求我的文件 x”,然后浏览器判断当前运行的 JavaScript 是否可以访问 x

如果您能容忍这样做带来的限制,您可以将其关闭,这就是 no-cors 所做的;它改变了浏览器的行为

因此,您希望看到 no-cors 是对浏览器的指令,并且使用您的 c#,您可以有效地将浏览器排除在等式之外,因此模仿它不太可能改变服务器行为。理论上是可以的;您的服务器可能被编码为拒绝访问最近没有看到 OPTIONS 请求的 url(CORS 模式下的浏览器首先发送一个选项),但实际上更可能的是根本原因更简单,就像您正在发布到一个被编码为期望 Get 的操作

【讨论】:

啊,所以只有当我将文件拖放到实际服务器上时,cors 才会起作用。我怎样才能为请求添加额外的选项,也许这是缺少的链接?所以我需要像这样请求一个标题Client.DefaultRequestHeaders. = 'dummy';?只有我不知道的某个选项。 这个答案有帮助。我可以通过 PUT 请求获得结果。 只有在浏览器中使用 JavaScript 发出请求时,CORS 才会相关。这是浏览器实现的一种复制保护功能,但是当您希望没有浏览器(您实际上是在编写自己的浏览器)时,CORS 的东西不适用。似乎最终的句子有望导致解决方案;服务器不接受您的 POST,但您使用 PUT 解决了它;这与期望 PUT 但接收 POST 的服务器一致 - 在这种情况下的响应应该是“方法不允许”

以上是关于如何使用“no-cors”将 JavaScript HTTP 发布请求代码更改为 C#?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 fetch() 中使用 no-cors

在将模式设置为“no-cors”时使用 fetch 访问 API 时出错 [重复]

使用带有模式的 fetch API:'no-cors',无法设置请求标头

将 no-cors 包含在标头中以获取 react.js 中的 json 内容时出现奇怪的错误

响应状态 = 0 使用 fetch polyfill 模式:'no-cors'

尝试使用 fetch 和 pass in 模式:no-cors