API 从 Word Web 加载项调用 (Office.Js) 不工作:CORS 问题?

API Call From Word Web Add-In (Office.Js) Is Not Working: CORS Issue?

朋友,

我正在尝试从 Word 加载项调用 API 并收到 "Access Denied" 错误。我做了一些研究,看起来 "Cross Origin Resource Sharing" 是原因。

1.网页 API

我在“http://localhost:61546/api/ORG_NAMES”本地托管 Web API 2 &我已启用 CORS 以接受所有来源,请参阅下面的 WebApiConfig。

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            var cors = new EnableCorsAttribute("*", "*", "*");
            config.EnableCors(cors);

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

2。测试应用程序

为了测试此 API 以确保它支持 CORS,我创建了以下页面并托管在 localhost:52799/home.html 上,我能够得到预期的响应。我已经在 IE 10 和 Chrome 中对此进行了测试。

<!DOCTYPE html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script>
    $(document).ready(function(){
        $("button").click(function () {
            var obj;
            .support.cors = true;
            $.getJSON("http://localhost:61546/api/ORG_NAMES/112233",
                function (data) {
                alert(data.ORG_ID);
            });
        });
    });
    </script>
</head> 
<body>
    <button>Click me</button>
</body>

3。 Word 加载项

现在我想从我的 Word Web 加载项中调用这个 API。来自不同主机 https://localhost:44339/ 的 Word 加载项 运行,请参见下面的代码。这里得到JSONreturns"Access Denied"。

      var OrgID; 
      $.getJSON("http://localhost:61546/api/ORG_NAMES/112233",
             function (data) {
                 OrgID = data.ORG_ID;
             });

另外,当我从 word 加载项调用 API 时,它不会 fiddler。

注意:这是 "Web Add-ins --> Word Add-in" 项目。

4。修复 - 需要帮助

不确定为什么我从 Word-Add-In 收到 "Access Denied" 错误,如果 CORS 是问题,那么我的测试应用程序 (#2) 不应该工作,对吗?

我试过使用“$.ajax”调用 JSON,"XMLHttpRequest" 但没有成功 work.I 可能缺少一些配置设置。

在此感谢任何帮助。 如果您需要更多信息,请告诉我。

由于这听起来像是 Office 加载项中的问题,而不是常规页面中的问题,您是否尝试过在清单文件中设置 AppDomains?请参阅 https://dev.office.com/docs/add-ins/overview/add-in-manifests

中的 "Specify domains you want to open in the add-in window"
<?xml version="1.0" encoding="UTF-8"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="TaskPaneApp">
<Id>c6890c26-5bbb-40ed-a321-37f07909a2f0</Id>
<Version>1.0</Version>
<ProviderName>Contoso, Ltd</ProviderName>
<DefaultLocale>en-US</DefaultLocale>
<DisplayName DefaultValue="Northwind Traders Excel" />
<Description DefaultValue="Search Northwind Traders data from Excel"/>
<AppDomains>
    <AppDomain>https://www.northwindtraders.com</AppDomain>
</AppDomains>
<DefaultSettings>
    <SourceLocation DefaultValue="https://www.contoso.com/search_app/Default.aspx" />
</DefaultSettings>
<Permissions>ReadWriteDocument</Permissions>
</OfficeApp>

如果您要进行 Ajax 调用,则不需要 Jsonp。您必须确保所有启动都使用 HTTPS,如果它以 HTTP 启动,它将阻止该流量。请记住,office-js 骨干是 IE 并且在那里;出于安全目的,api 将只允许 HTTPS

更新

请记住,一个 office-js 插件实际上是两个项目,您必须确保您的项目都在 HTTPS 中启动。另外,我会查看 Manifest 文件并查看您的源代码并确保它指向 HTTPS

我在使用 ajax 时遇到了同样的问题,无法调用 web-api.NET MVC。

Web api 端(服务器端):

  1. 在 Web api 中实施 CORS,因为 excel office.js 在不同的端口上工作,并在 excel 内绑定服务器的代理对象,同时保留 Web api在另一个端口上,因此它与在本地拥有 2 个不同的域一样好,因此浏览器会自动阻止发出的请求。

所以需要跨源资源共享。

  1. 为 Web api 启用 Https。 http://csharp-video-tutorials.blogspot.com/2016/09/aspnet-web-api-enable-https.html

客户端

  1. 只需使用 ajax 拨打电话,如下所示。 url: 'https://localhost:44319/api/Default/PostItems' 注意:https:是强制要求的。

    function makeAjaxCall(rangeJSON) {
    
    $.ajax({
        url: 'https://localhost:44319/api/Default/PostItems',
        type: 'POST',
        data: rangeJSON,
        contentType: 'application/json;charset=utf-8',
    }).done(function (data) {
        console.log(data)
      app.showNotification(data.Status, data.Message);
    }).fail(function (status) {
       app.showNotification('Error', 'Could not communicate with the server.');
        }).always(showResponse);
    
    }
    
    
    function exceltojson() {
    Excel.run(function (ctx) {
    
        var range = ctx.workbook.worksheets.getItem("Sheet1").getRange("A1:BO765");
    
        range.load("values, numberFormat");
    
        ctx.sync().then(
            function () {
    
               makeAjaxCall(JSON.stringify(range.values));
    
            }).catch(function (error) {
                console.log(error);
    
            });
    });
    
    
    function showResponse(object) {
    
        console.log(object);
        $("#output").text(JSON.stringify(object,null, 4));
    }