Azure自定义控制器/API .Net后端

31

我在Azure上运行了一个MobileService,并决定创建一个新的服务并自己迁移代码。新服务是一种新型号称为:Azure Mobile App Service。

目前,我的身份验证正在工作,并且可以进行迁移/更新数据库。我正在遵循TodoItem示例。现在,我想创建自己的自定义API,在MobileService上很容易工作,但我无法在Azure Mobile App上使其工作 :/

我已经按照这两个链接 web-Api-routingapp-service-mobile-backend 进行了跟随。现在我有以下内容:

我创建了一个新的控制器:

[MobileAppController]
public class TestController : ApiController
{
    // GET api/Test
    [Route("api/Test/completeAll")]
    [HttpPost]
    public async Task<ihttpactionresult> completeAll(string info)
    {
        return Ok(info + info + info);
    }
}

在mobileApp.cs文件中,我根据后端文档添加了以下代码:
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();

另外,根据 web-api-routing,我已经安装了以下软件包:

Microsoft.AspNet.WebApi.WebHost 

并且客户端的请求:

string t = await App.MobileService.InvokeApiAsync<string,string>("Test/completeAll", "hej");

调试显示,这是正确的URL:

{方法:POST,请求URI:'https://xxxxxxx.azurewebsites.net/api/Test/completeAll', 版本:1.1,内容:System.Net.Http.StringContent,头文件:{X-ZUMO-FEATURES: AT X-ZUMO-INSTALLATION-ID: e9b359df-d15e-4119-a4ad-afe3031d8cd5 X-ZUMO-AUTH: xxxxxxxxxxx Accept: application/json User-Agent: ZUMO/2.0 User-Agent: (lang=Managed; os=Windows Store; os_version=--; arch=Neutral; version=2.0.31125.0) X-ZUMO-VERSION: ZUMO/2.0 (lang=Managed; os=Windows Store; os_version=--; arch=Neutral; version=2.0.31125.0) ZUMO-API-VERSION: 2.0.0 Content-Type: application/json; charset=utf-8 Content-Length: 3}}

但是一直收到404(未找到)错误。

我错过了什么吗 :/ ?

更新

我尝试在mobileApp.cs中扩展代码:

HttpConfiguration config = new HttpConfiguration();
        new MobileAppConfiguration()
            .UseDefaultConfiguration().MapApiControllers()
            .ApplyTo(config);
        config.MapHttpAttributeRoutes();
        app.UseWebApi(config);

基于应用服务后端,但仍然无法访问 :/。

更新

我使用fiddler2通过浏览器访问终结点并获得以下结果:

Fiddler output

再次更新

我尝试创建另一个最小化的解决方案,但仍然遇到相同的错误。是否有任何很好的教程可以供我遵循以实现此功能?

积极的感觉正在逐渐消失...

该问题现在也在msdn上运行,如果有任何信息显示,我将在此处进行更新。


更新

测试了Linda的评论,事实上我可以访问值转换器:

// Use the MobileAppController attribute for each ApiController you want to use  
// from your mobile clients 
[MobileAppController]
public class ValuesController : ApiController
{
    // GET api/values
    public string Get()
    {
        MobileAppSettingsDictionary settings = this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
        ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();

        string host = settings.HostName ?? "localhost";
        string greeting = "Hello from " + host;

        traceWriter.Info(greeting);
        return greeting;
    }

    // POST api/values
    public string Post()
    {
        return "Hello World!";
    }

}

我可以使用post和get函数访问这个内容:

string t = await App.MobileService.InvokeApiAsync<string, string>("values", null, HttpMethod.Post, null);

或者

string t = await App.MobileService.InvokeApiAsync<string, string>("values", null, HttpMethod.Get, null);

但是,我贴的代码没有路由,为什么可以使用值访问它?如果不使用路由参数,原始控制器的路径会是什么?
额外信息 我现在已经向Microsoft创建了一个支持工单,并将更新其他信息.... 希望如此。 更新 来自MSDN论坛的信息:尝试使用MS_SkipVersionCheck 在这里阅读有关该属性的信息,似乎不适用。但是我尝试了它。对于我的API仍然是“未找到”,但原始API仍然有效。因此,它对此问题没有影响。

尝试重新构建您的解决方案,并在发布时勾选“在目标位置删除其他文件”。同时,请确保您正在使用最新版本的服务器 SDK,当前版本为1.1.157。https://www.nuget.org/packages/Microsoft.Azure.Mobile.Server/ - lindydonna
@lindydonna-msft 我电脑上安装的版本是1.1.157.1,所以我认为这是最新的 :) (我的系统上没有任何软件包更新)。我已经进行了重建检查,“删除…”并重新发布。. . . 相同的错误仍然存在(404),使用fiddler也没有更好的响应。您知道有没有可行的最小解决方案,我可以得到?所以我只需要更改连接字符串? - JTIM
1
如果您使用快速入门项目会发生什么?它将为您安装一个API控制器。您能够访问那个控制器吗? - lindydonna
1
你可以将你的服务器项目发送到mobileservices@microsoft.com吗?我无法重现你所描述的问题。(在压缩前确保清理你的项目,以减少附件大小。) - lindydonna
1
抱歉,我打错了。正确的地址是mobileservices@microsoft.com - lindydonna
显示剩余7条评论
5个回答

15

是的!!!

我终于搞定了,我从lidydonn - msft的git复制了使用方法,并阅读了有关移动服务的.net后端

这最终得到了以下结果:

using System.Web.Http;
using Microsoft.Azure.Mobile.Server.Config;
using System.Threading.Tasks;
using System.Web.Http.Tracing;
using Microsoft.Azure.Mobile.Server;

namespace BCMobileAppService.Controllers
{
[MobileAppController]
public class TestController : ApiController
{
    // GET api/Test
    [HttpGet, Route("api/Test/completeAll")]
    public string Get()
    {
        MobileAppSettingsDictionary settings = this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
        ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();

            string host = settings.HostName ?? "localhost";
            string greeting = "Hello from " + host;

            traceWriter.Info(greeting);
            return greeting;
        }

        // POST api/values
        [HttpPost, Route("api/Test/completeAll")]
        public string Post(string hej)
        {
            string retVal = "Hello World!" + hej;
            return retVal;
        }
    }
}

这是一个新的控制器,不是像lidydonna使用的那个。它似乎想要同时具有getpost函数。这导致API被注册并且可以被访问。这意味着我所使用的客户端调用服务器的方式是:

t = await App.MobileService.InvokeApiAsync<string, string>("Test/completeAll", null, HttpMethod.Post, new Dictionary<string, string>() { { "hej", " AWESOME !" }});

dialog = new MessageDialog(t);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();

我收到了回复,太好了!

额外信息

创建的控制器类必须以Controller结尾,可以在之前添加文本但不能在之后添加。这个信息在MSDN论坛讨论中提供。

如果postget具有相同的输入,则服务器返回Not found。使用不同的输入可以解决这个问题。

如果出现奇怪的Internal Server Error,即使你可以逐步检查整个服务器代码,并且想要返回的所有变量都已初始化,但客户端仍然收到错误。那么请参考内部服务器错误 - Azure应用服务自定义控制器,其中简单的配置修复可以解决这个问题。


1
仍然没有ZUMO-API-VERSION头,它无法工作:http://go.microsoft.com/fwlink/?LinkId=690568#2.0.0 - Andrei Drynov
@AFD 我认为当您使用Azure命令InvokeApiAsync()时,这个问题就已经解决了?至少我没有遇到任何问题。您能描述一下您如何访问API吗? - JTIM
我使用了 Fiddler/Postman。猜测可以设置断点并从另一个项目调用 InvokeApiAsync。 - Andrei Drynov
@AFD 我记得旧版本的Azure Muget包和SDK在初始化时需要密钥。你确定你有Azure SDK 2.8.1和正确的Muget包(我现在想不起来是哪个了:D)? - JTIM
1
我的个人英雄! - Sean Stayns
显示剩余2条评论

5
你的项目配置可能有误。我这里有一个运行良好的示例:https://gist.github.com/lindydonna/6fca7f689ee72ac9cd20。在创建HttpConfiguration对象后,调用config.MapHttpAttributeRoutes()。我添加了路由属性[Route("api/Test/completeAll")]并确认该路由已正确注册。尝试将此属性添加到ValuesController中并检查路由。

我已经复制了你的using语句。有时候会出现太多链接到相同地址的情况(好的,很棒它们存在)。删除清理上传新的,只有一个路由,错误返回“未找到”。 我将Task<>改为了get set函数,但现在出现了方法不允许的错误。我简直无法理解服务器上出了什么问题:/ - JTIM

2
我发现使用属性路由时,404错误的另一个原因。
上面的代码最初在mobileApp.cs中有这样一段:
HttpConfiguration config = new HttpConfiguration();
    new MobileAppConfiguration()
        .UseDefaultConfiguration().MapApiControllers()
        .ApplyTo(config);
    config.MapHttpAttributeRoutes();
    app.UseWebApi(config);

需要将config.MapHttpAttributeRoutes()移动到.ApplyTo之上:

HttpConfiguration config = new HttpConfiguration();
 config.MapHttpAttributeRoutes();
 new MobileAppConfiguration()
        .UseDefaultConfiguration().MapApiControllers()
        .ApplyTo(config);

1
尝试将继承自ApiController改为TableController。

我稍后会尝试这个。然而文档中明确指出它应该是ApiController?但我会试一下 :) - JTIM
对于这种用例,ApiController 更加合适。 - lindydonna
@lindydonna-msft,什么情况下使用ApiController比TableController更合适?我刚开始使用Azure App Service,希望有更多细节来帮助我决定何时使用哪个。 - HappyNomad
@lindydonna-msft 通过“逻辑实体”,我猜你指的是表格行而不包括关联数据,因为TableController不会检索或更新关联数据。为什么要限制我的ApiController只有一个操作?例如,我可能有一个操作来插入或更新根实体及其相关数据,还有另一个操作来删除它。 - HappyNomad
ApiController可以有多个操作,但如果您只有一个操作,则ApiController可能是正确的选择。逻辑实体是指您正在执行CRUD操作的DTO。它不必映射到一个数据库表。 - lindydonna
显示剩余4条评论

1

很奇怪,但简单的 API 请求在 Azure 应用服务中无法工作。所以我找到了解决方案,这对我有用。我已经使用 C# 的 http post/get、Android 的 post/get 和 Objective C 的 post/get 进行了测试。 首先,您需要更新 Startup.MobileApp.cs 类:

  new MobileAppConfiguration()
    .UseDefaultConfiguration()   
    .MapApiControllers()                /* /api endpoints **missing part***/ 
    .ApplyTo(config);

创建 Azure 移动应用自定义控制器。然后修改您的控制器,以获得适当的 JSON 响应。
    public class Mes
    {
        public string message { get; set; }
    }

    // GET api/My
    public Mes Get()
    {

        return new Mes { message = "thanks" };


       // return "Hello from custom controller!";
    }
    // POST api/My
    public Mes Post(Mes chal)
    {

        return new Mes { message = chal.message + "asnwer" };


        // return "Hello from custom controller!";
    }
}

您可以简单地离开第一个变量并获得响应,但是Objective C会告诉您JSON文本没有以数组或对象开始,并提供允许片段的选项...等等。这是因为您获取的是简单字符串而不是对象。所以我已经用Mes类修改了我的响应。
但是这也取决于您如何发出请求和期望什么类型的对象。所以.MapApiControllers()是API的主要关键,WEB API控制器现在已更改为Azure自定义控制器。
希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接