ServiceStack“可自定义字段”

时间:2016-03-16 18:30:58

标签: servicestack

我们一直在使用SS Customizable Fields(查询字符串中的“fields =”),我想我们可能在某个地方缺少配置。对我们来说,字段名称似乎区分大小写 - 如果它们与DTO不匹配,则不会返回。但是,对于从AutoQuery GitHub页面链接的示例(更改外壳仍会导致正确的字段返回),情况并非如此:

github.servicestack.net/repos.json?fields=Name,Homepage,Language,Updated_At

我们缺少什么?

谢谢!

以下是展示我们所看到的行为的示例:

APPHOST:

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

namespace TestSS.Service {
    public class AppHost : AppHostBase {
        public AppHost()
            : base("TestSS Service", typeof(AppHost).Assembly) {
        }

        public override void Configure(Funq.Container container) {
            Plugins.Add(new AutoQueryFeature { EnableUntypedQueries = false });
            Plugins.Add(new CorsFeature());

            PreRequestFilters.Add((httpReq, httpRes) => {
                if (httpReq.Verb == "OPTIONS")
                    httpRes.EndRequest();
            });

            container.Register<IDbConnectionFactory>(
                new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["TestSS"].ConnectionString, SqlServerDialect.Provider));

            JsConfig.DateHandler = DateHandler.ISO8601;
            JsConfig.IncludeNullValues = true;
            JsConfig.EmitCamelCaseNames = true;
        }
    }
}

的DTO:

using ServiceStack.DataAnnotations;

namespace TestSS.DTO {
    public class Employee {
        [PrimaryKey]
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        [References(typeof(Department))]
        public int DepartmentId { get; set; }

        [Ignore]
        public Department Department { get; set; }
    }


    public class Department {
        [PrimaryKey]
        public int Id { get; set; }
        public string Name { get; set; }
    }

}

服务:

using ServiceStack;
using TestSS.DTO;

namespace TestSS.Service.Services {
    [Route("/employees/{Id}", "GET")]
    public class SingleEmployeeRequest : QueryBase<Employee> {
        public string Id { get; set; }
    }

    [Route("/employees", "GET")]
    public class FindEmployeesRequest : QueryBase<Employee>, IJoin<Employee, Department> {
    }
}

尝试以下路线:

/employees?fields=FirstName,LastName  <-- works

/employees?fields=firstname,LastName  <-- Only LastName returned

/employees?fields=firstname,lastname  <-- All properties returned ?

现在,从Employee服务中的FindEmployeesRequest中删除 IJoin ,然后再次尝试路由。

/employees?fields=FirstName,LastName  <-- works

/employees?fields=firstname,LastName  <-- works

/employees?fields=firstname,lastname  <-- works

更新:

套管问题以4.0.55修正,但这条路线似乎还有一个奇怪的行为:

/employees?fields=departmentid

响应包含DepartmentId AND Id属性,ID值实际上是 DepartmentId 值。这条路线也是如此:

/employees?fields=id,departmentid

1 个答案:

答案 0 :(得分:2)

支持不区分大小写的自定义字段in this commit添加了tests for AutoQuery in this commit。此更改可从v4.0.55获得,现在为available on MyGet

您现在可以使用区分大小写的自定义字段,但如果您选择升级到最新版本,则可以使用AutoQuery进行一些重命名更改,稍后将在下一个v4.0.56发行说明中对此进行说明。

由于新的非RDBMS版本的AutoQuery支持自定义数据源(称为AutoQueryData),我们不得不重命名一些现有的AutoQuery属性,以便它们在两个实现之间保持一致的隔离命名。

命名更改会在obsoleted attributes中捕获,实际上涉及为您正在使用的任何Db属性或[Query]类添加QueryBase<T>后缀,即:< / p>

[Obsolete("Use [QueryDb]")]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class QueryAttribute : AttributeBase { }

[Obsolete("Use [QueryDbField]")]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class QueryFieldAttribute : AttributeBase { }

[Obsolete("Use QueryDb")]
public abstract class QueryBase<T> : QueryBase, IQueryDb<T>, IReturn<QueryResponse<T>> { }

[Obsolete("Use QueryDb")]
public abstract class QueryBase<From, Into> 
    : QueryBase, IQueryDb<From, Into>, IReturn<QueryResponse<Into>> { }

[Obsolete("Use IQueryDb<From>")]
public interface IQuery<From> : IQueryDb { }
[Obsolete("Use IQueryDb<From,Into>")]
public interface IQuery<From, Into> : IQueryDb { }

虽然仍然支持使用现有的QueryBase类,但现在已经过时,您应该在自己的闲暇时切换到新的QueryDb基类。

所以而不是:

[Route("/movies")]
public class FindMovies : QueryBase<Movie>
{
    public string[] Ratings { get; set; }
}

要使用的新基类是QueryDb,例如:

[Route("/movies")]
public class FindMovies : QueryDb<Movie>
{
    public string[] Ratings { get; set; }
}

发行说明explains the Custom Fields behavior

  

仍然需要在Response DTO上定义Fields,因为此功能不会更改Response DTO Schema,只会填充哪些字段。这确实改变了执行的底层RDBMS SELECT,同时也受益于RDBMS和App Server之间的带宽减少。

     

在指定自定义字段时可以添加的有用的JSON自定义是ExcludeDefaultValues,例如:

/query?Fields=Id,Name,Description,JoinTableId&jsconfig=ExcludeDefaultValues

这将从JSON响应中删除具有默认值的任何值类型字段,例如:

基本上只有您选择的字段在Response DTO上被查询和填充,所有其他字段的默认值对于引用类型为null但对于ValueTypes,对于Date,0为DateTime是DateTime.MinValue等等。

?jsconfig=ExcludeDefaultValues修饰符指示ServiceStack的JSON Serializer忽略序列化的默认值属性,因此上面的链接将返回:

{
    Total: 30,
    Results: [
    {
        Name: "ServiceStack",
        Homepage: "https://servicestack.net",
        Language: "C#",
        Updated_At: "/Date(1443370980000+0000)/"
    },
    {
        Name: "ServiceStack.Examples",
        Homepage: "https://servicestack.net",
        Language: "C#",
        Updated_At: "/Date(1443326228000+0000)/"
    },
    ...
}