【问题标题】:ServiceStack Request BodyServiceStack 请求正文
【发布时间】:2014-01-12 15:58:12
【问题描述】:

我正在尝试在 servicestack 和 ormlite 中编写我的第一个 REST 服务。情况不会太糟。

我已经编写了代码来显示所有记录、基于 ID 的记录并删除基于 ID 的记录。

现在我开始添加和编辑记录,我对如何从调用的请求正文中获取数据感到困惑。

我正在做一个

POST: http://localhost:7571/equipment/create/123

请求正文为

[{"eMCo":"1","equipment":"DP112","location":"Field","manufacturer":"","model":"","modelYr":"2013","vinNumber":"","description":"Trevor","status":"A","attachToEquip":"BR118","licensePlateNo":""}]

但在我的服务中,我无法弄清楚如何在此函数中访问请求正文数据:

public object Post(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            //base.Request.FormData[""]
            db.Insert(request);
        }
        return null;
    }

这是完整的代码...如果您能指出我做错的任何事情,请做!

using ServiceStack;
using ServiceStack.OrmLite;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;

namespace ViewPoint
{
[Api("Enables viewiing, creation, updating and deletion of equipment from the EMEM table.")]
[Route("/equipment", "GET")]
[Route("/equipment/detail/{equipment}", "GET")]
[Route("/equipment/delete/{equipment}", "DELETE")]
[Route("/equipment/update/{equipment}", "PATCH")]
[Route("/equipment/create/{equipment}", "POST")]

public class EMEMTrev
{
    public string eMCo { get; set; }
    public string equipment { get; set; }
    public string Location { get; set; }
    public string Manufacturer { get; set; }
    public string Model { get; set; }
    public string ModelYr { get; set; }
    public string VINNumber { get; set; }
    public string Description { get; set; }
    public string Status { get; set; }
    public string AttachToEquip { get; set; }
    public string LicensePlateNo { get; set; }
}

public class EMEMTrevResponse
{
    public string eMCo { get; set; }
    public string equipment { get; set; }
    public string Location { get; set; }
    public string Manufacturer { get; set; }
    public string Model { get; set; }
    public string ModelYr { get; set; }
    public string VINNumber { get; set; }
    public string Description { get; set; }
    public string Status { get; set; }
    public string AttachToEquip { get; set; }
    public string LicensePlateNo { get; set; }
    public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized
}


public class EquipmentService : Service
{
    public object Get(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            if (request.equipment == null)
            {
                List<EMEMTrev> results = db.Select<EMEMTrev>();
                return results;
            }
            else
            {
                List<EMEMTrev> results = db.Select<EMEMTrev>(p => p.Where(ev => ev.equipment == request.equipment));
                return results;
            }

        }
    }
    public object Delete(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            db.Delete<EMEMTrev>(p => p.Where(ev => ev.equipment == request.equipment));
        }
        return null;
    }

    public object Post(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            //base.Request.FormData[""]
            db.Insert(request);
        }
        return null;
    }

    public object Patch(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            db.Update(request);
        }
        return null;
    }
}
}

任何帮助将不胜感激!

谢谢

更新代码:

ServiceEquipment.cs

using ServiceStack;
using ServiceStack.OrmLite;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Web;

namespace ViewPoint
{
[Api("Enables viewiing, creation, updating and deletion of equipment from the EMEM table. Use a POST to create an EMEM or a PUT to update one.")]
[Route("/equipment", "GET,POST,PUT")]
[Route("/equipment/{equipment}", "GET,DELETE")]

public class EMEMTrev
{
        public string eMCo { get; set; }
        public string equipment { get; set; }
        public string location { get; set; }
        public string manufacturer { get; set; }
        public string model { get; set; }
        public string modelYr { get; set; }
        public string vinNumber { get; set; }
        public string description { get; set; }
        public string status { get; set; }
        public string attachToEquip { get; set; }
        public string licensePlateNo { get; set; }

}

public class EMEMTrevResponse
{
    public EMEMTrev emem { get; set; }
    public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized
}


public class EquipmentService : Service
{
    public object Get(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
                    using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            if (request == null)
            {
                List<EMEMTrev> results = db.Select<EMEMTrev>();
                return results;
            }
            else
            {
                List<EMEMTrev> results = db.Select<EMEMTrev>(p => p.Where(ev => ev.equipment == request.equipment));

                return results;
            }

        }
    }
    public object Delete(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            db.Delete<EMEMTrev>(p => p.Where(ev => ev.equipment == request.equipment));
        }
        return new HttpResult
        {
            StatusCode = HttpStatusCode.NoContent,
            Headers =
                           {
                               {HttpHeaders.Location, this.Request.AbsoluteUri.CombineWith(request.equipment)}
                           }
        };
    }

    public object Post(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            db.Insert(request);
        }
        return new HttpResult()
        {
            StatusCode = HttpStatusCode.Created,
            Headers =
                           {
                               {HttpHeaders.Location, base.Request.AbsoluteUri.CombineWith(request.equipment)}
                           }
        };
    }

    public object Put(EMEMTrev request)
    {
        var dbFactory = new OrmLiteConnectionFactory("Data Source=(local);Initial Catalog=Kent;Integrated Security=True", SqlServerDialect.Provider);
        using (IDbConnection db = dbFactory.OpenDbConnection())
        {
            db.Update(request);
        }
        return new HttpResult
        {
            StatusCode = HttpStatusCode.NoContent,
            Headers =
                           {
                               {HttpHeaders.Location, base.Request.AbsoluteUri.CombineWith(request.equipment)}
                           }
        };
    }
}

}

AppHost.cs:

using System.Configuration;
using ServiceStack;
using ServiceStack.Auth;
using ServiceStack.Configuration;
using ServiceStack.Data;
using ServiceStack.OrmLite;

[assembly: WebActivator.PreApplicationStartMethod(typeof(ViewPoint.App_Start.AppHost), "Start")]


/**
* Entire ServiceStack Starter Template configured with a 'Hello' Web Service and a 'Todo' Rest Service.
*
* Auto-Generated Metadata API page at: /metadata
* See other complete web service examples at: https://github.com/ServiceStack/ServiceStack.Examples
*/

namespace ViewPoint.App_Start
{
public class AppHost : AppHostBase
{       
    public AppHost() //Tell ServiceStack the name and where to find your web services
        : base("StarterTemplate ASP.NET Host", typeof(EquipmentService).Assembly) { }

    public override void Configure(Funq.Container container)
    {
        //Set JSON web services to return idiomatic JSON camelCase properties
        ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;

        //Configure User Defined REST Paths
        //Routes
        //  .Add<Hello>("/hello")
        //  .Add<Hello>("/hello/{Name*}");

        //Uncomment to change the default ServiceStack configuration
        //SetConfig(new HostConfig {
        //});

        //Enable Authentication
        //ConfigureAuth(container);

        //Register all your dependencies
        //container.Register(new TodoRepository());         
    }

    /* Example ServiceStack Authentication and CustomUserSession */
    private void ConfigureAuth(Funq.Container container)
    {
        var appSettings = new AppSettings();

        //Default route: /auth/{provider}
        Plugins.Add(new AuthFeature(() => new CustomUserSession(),
            new IAuthProvider[] {
                new CredentialsAuthProvider(appSettings), 
                new FacebookAuthProvider(appSettings), 
                new TwitterAuthProvider(appSettings), 
                new BasicAuthProvider(appSettings), 
            })); 

        //Default route: /register
        Plugins.Add(new RegistrationFeature()); 

        //Requires ConnectionString configured in Web.Config
        var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
        container.Register<IDbConnectionFactory>(c =>
            new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));

        container.Register<IUserAuthRepository>(c =>
            new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));

        container.Resolve<IUserAuthRepository>().InitSchema();
    }

    public static void Start()
    {
        new AppHost().Init();
    }
}

}

【问题讨论】:

  • 我注意到的第一件事是您的 JSON 样本是数组中的一个对象:[{...}],但您的请求 DTO 是一个普通对象。如果您删除这些方括号,使您的 JSON 看起来像 {...},您的应用程序会表现得更好吗?
  • @esker 谢谢 - 试过了。没有变化:(
  • 您能否更详细地解释一下具体的问题是什么? Post 请求中的 request 对象是否为空,即使从请求 JSON 中删除了方括号?或者request 对象中是否有个别属性意外为空?还是在您发送请求时甚至没有调用 Post 方法?等
  • @TrevorDaniel 我很困惑你为什么要访问原始身体数据。特别是如果您发送的原始数据是 JSON,并且会自动反序列化为您的方法的请求参数。如果您发送有效的 JSON,那么您的数据应该可以使用 request.Descriptionrequest.ModelYr 等访问。您使用什么客户端发送请求?
  • @Scott 嗨,你可能已经发现了我的错误。当我打电话给 POST:localhost:7571/equipment/create/123 我可以看到“123”但我看不到“描述”,例如它是空的,这就是为什么我认为我必须做一些事情来阅读请求正文?客户端? - 我一直在尝试用 Fiddler 调用函数

标签: c# servicestack ormlite-servicestack


【解决方案1】:

您的问题与 JSON 数据和 DTO 之间的大小写差异有关。映射区分大小写。 equipment 参数已填充,因为大小写匹配,但其余属性不匹配。

您可以通过将此行添加到您的 AppHost 配置来解决此问题。

JsConfig.EmitCamelCaseNames = true;

这会将序列化程序设置为将 JSON 数据中的 location 映射到 DTO 中的 Location和其他属性,并在序列化时处理返回的转换。

因此您可以访问请求参数上的属性,而不是通过原始数据。


您的服务看起来不错。我无法立即看到它有任何问题,我认为问题可能在于您如何调用服务。

以下这些方法将有助于调试问题。我建议您尝试使用这个简单的 HTML 页面调用客户端,看看是否填充了必填字段。

创建一个文件,将其命名为test.html,并将其与您的ServiceStack 服务程序集一起放入bin 文件夹中,然后导航到您的服务路径http://localhost:7571/test.html

<!doctype html>
<html>
    <head>
        <title>Test</title>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script>
            function send()
            {
                // Send data to the service
                $.ajax({
                    type: "POST",
                    url: "/equipment/create/DP112",
                    contentType: "application/json",
                    data: JSON.stringify({
                        eMCo: "1",
                        equipment: "DP112",
                        location: "Field",
                        manufacturer: "",
                        model: "",
                        modelYr: "2013",
                        vinNumber: "",
                        description: "Trevor",
                        status: "A",
                        attachToEquip: "BR118",
                        licensePlateNo: ""
                    })
                }).done(function(result){

                });
            }
        </script>
</head>
<body>
    <button onclick="send()">Send Request</button>
</body>
</html>

此 html 文件应提供格式正确的请求。

还可以考虑通过将此行添加到您的 AppHost 配置来添加请求记录器。然后转到http://localhost:7571/requestlogsSee here 了解更多信息。

Plugins.Add(new RequestLogsFeature());

请求内容类型:

如果客户端请求上没有设置正确的内容类型,那么 ServiceStack 将不会将值填充到请求中。将请求中的contentType 设置为application/json 有效。

【讨论】:

  • 很奇怪。我已经在我的应用程序中拥有它......但仍然看不到传入的值......我会继续寻找。一定是我在做的傻事......
  • @TrevorDaniel 您能否更新您的问题以包含您的 AppHost 配置?
  • @TrevorDaniel 我已更新我的答案以帮助提供调试说明。
  • 令人难以置信的请求仍然是空的! - 我很难过
  • 我在 ConfigureAuth 的 apphost.cs 中添加了插件,但我得到一个 404 试图访问 /requestlogs - 我一定在前世做过一些事情来让 SS 不安。
猜你喜欢
  • 2013-07-05
  • 1970-01-01
  • 2013-04-02
  • 1970-01-01
  • 2012-09-19
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多