Azure移动服务TableController不返回内部对象 [英] Azure Mobile Service TableController not returning inner objects

查看:56
本文介绍了Azure移动服务TableController不返回内部对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用表存储创建一个基本的(我的第一个)Azure移动服务,以控制一个简单的事件"应用程序.我的DataObjects包含2种对象类型:CoordinatorEvent,我希望Coordinators是一个单独的表来存储特定的信息,我不希望它在Events中进行非规范化,但是Events也有一个内部对象Location要存储活动位置的详细信息,但我想存储非规范化的信息,因为我不想与活动分开维护此详细信息.

I am creating a basic (my first) Azure Mobile Service with Table Storage to control a simple Events app. My DataObjects consists of 2 object types: Coordinator and Event, I want Coordinators to be a separate table to store specific info that I don't want it denormalized inside the Events, but Events also has a inner object Location to store details for the event's location, but that I want to store denormalized as I don't want to maintain this details separately from the Event.

这里是我到目前为止拥有的对象: 数据对象:

Here the objects I have so far: DataObjests:

public class Coordinator : EntityData {
    public string Name { get; set; }
    public int Points { get; set; }
    public bool IsActive { get; set; }
}
public class Event: EntityData {
        public Coordinator Coordinator { get; set; }
        public DateTime EventDate { get; set; }
        public int Attendees { get; set; }
        public Location Location { get; set; }
}
public class Location {
        public string Name { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string City { get; set; }
        public string County { get; set; }
        public string PostCode { get; set; }
}

由VS的脚手架生成的作为基本TableController的控制器,我所做的唯一更改是在事件控制器上公开了MobileServiceContext,以使Post方法在保存时能够找到现有的协调器,因为客户端仅会发布协调人的ID:

The controllers as basic TableController generated by VS's scaffolding, the only change I made was to expose the MobileServiceContext on the Event Controller to enable the Post method to find an existing Coordinator when saving as the client will only post the Coordinator's ID:

public class EventController : TableController<Event> {
        private MobileServiceContext context;
        protected override void Initialize(HttpControllerContext controllerContext) {
            base.Initialize(controllerContext);
            context = new MobileServiceContext();
            DomainManager = new EntityDomainManager<Event>(context, Request, Services);
        }
        protected override void Dispose(bool disposing) {
            context?.Dispose();
            base.Dispose(disposing);
        }

        public IQueryable<Event> GetAllEvent() {
            return Query();
        }

        public async Task<IHttpActionResult> PostEvent(Event item) {
            var coordinator = context.Coordinators.Find(item.Coordinator.Id);
            item.Coordinator = coordinator;
            Event current = await InsertAsync(item);
            return CreatedAtRoute("Tables", new { id = current.Id }, current);
        }

}

从客户端发布数据按预期工作,我有一个带有正确数据的Coordinator表:

Posting data from the client works as expected, I have a Coordinator table with the right data:

ID  Name    Points  IsActive    Version CreatedAt   UpdatedAt   Deleted
cdf96b0f93644f1e945bd16d63aa96e0    John Smith  10  True    0x00000000000007D2  04/09/2015 09:15:02 +00:00  04/09/2015 09:15:02 +00:00  False
f216406eb9ad4cdcb7b8866fdf126727    Rebecca Jones   10  True    0x00000000000007D4  04/09/2015 09:15:30 +00:00  04/09/2015 09:15:30 +00:00  False

与第一个协调员相关的事件:

And a Event associated to the first Coordinator:

Id  EventDate   Attendees   Location_Name   Location_Address1   Location_Address2   Location_City   Location_County Location_PostCode   Version CreatedAt   UpdatedAt   Deleted Coordinator_Id
961abbf839bf4e3481ff43a214372b7f    04/11/2015 09:00:00 0   O2 Arena    Peninsula Square        London      SE10 0DX    0x00000000000007D6  04/09/2015 09:18:11 +00:00  04/09/2015 09:18:11 +00:00  False   cdf96b0f93644f1e945bd16d63aa96e0

这一切看起来都不错,我的两个问题是事件的获取,其中既不返回CoordinatorLocation对象,而EventController的Get的Json就是这样:

At this point all looks good, my 2 problems are with the Get of the Event, where both Coordinator and Location objects are not returned and the Json of my EventController's Get is simply this:

[{"id":"961abbf839bf4e3481ff43a214372b7f","attendees":0,"eventDate":"2015-11-04T09:00:00Z"}]

所以我的两个问题是:

1)服务器上的EventController正确加载了Location对象,如果返回之前中断,我可以看到正确加载的属性,对我来说这看起来像是Json序列化问题,但是我已经尝试更改串行器的配置(在WebApiConfig上)没有太大影响,我尝试的最后一个选项是MaxDepth,但仍然没有返回Location对象.

1) The Location object is loaded correctly by the EventController on the server, I can see the properties correctly loaded if I break before returning, what for me looks like a Json serialization problem, but I already tried to change the serializer's configuration (on WebApiConfig) without much effect, the last option I tried was the MaxDepth but still the Location object is not returned.

2)我根本没有在服务器上加载过的Coordinator对象,甚至是ID(也没有正确地存储在表中)也没有加载,因此我无法强制加载整个对象,当然也不会将其返回给客户.

2) The Coordinator object I not loaded on the server at all, not even the Id (that is correctly stored on the table) so I cant force the load of the entire object, and of course it isn't returned to the client.

对我在这里做错的任何想法吗?

Any ideas on what I am doing wrong here?

预先感谢

克莱顿·洛瓦托(Claiton Lovato)

Claiton Lovato

推荐答案

这是TableController的默认行为. 为了以一种时尚的方式实现您要寻找的东西,您应该在控制器中实现OData $ expand .

This is default behavior for TableController. In order to achieve what you're looking for, in a fashion way, you should implement OData $expand in your controller.

本文为解决方案提供了很好的演练

This article provides a good walk-throughout for the solution
Retrieving data from 1:n relationship using .NET backend Azure Mobile Services

作为进一步的扩展,我实现了一个自定义属性,您可以在控制器方法中使用该属性来指定客户端可以请求扩展的属性.您可能不希望总是返回所有子关系(扩展的对象)

As further extension, I've implemented a custom attribute that you can use in your controller methods to specify which properties the client can request to expand. You may not want to always returned all child relationships (expanded objects)

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class ExpandablePropertyAttribute : ActionFilterAttribute
{
    #region [ Constants ]
    private const string ODATA_EXPAND = "$expand=";
    #endregion

    #region [ Fields ]
    private string _propertyName;
    private bool _alwaysExpand;
    #endregion

    #region [ Ctor ]
    public ExpandablePropertyAttribute(string propertyName, bool alwaysExpand = false)
    {
        this._propertyName = propertyName;
        this._alwaysExpand = alwaysExpand;
    }
    #endregion

    #region [ Public Methods - OnActionExecuting ]
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        base.OnActionExecuting(actionContext);
        var uriBuilder = new UriBuilder(actionContext.Request.RequestUri);
        var queryParams = uriBuilder.Query.TrimStart('?').Split(new char[1] { '&' }, StringSplitOptions.RemoveEmptyEntries).ToList();
        int expandIndex = -1;

        for (var i = 0; i < queryParams.Count; i++)
        {
            if (queryParams[i].StartsWith(ODATA_EXPAND, StringComparison.Ordinal))
            {
                expandIndex = i;
                break;
            }
        }

        if (expandIndex >= 0 || this._alwaysExpand)
        {
            if (expandIndex < 0)
            {
                queryParams.Add(string.Concat(ODATA_EXPAND, this._propertyName));
            }
            else
            {
                queryParams[expandIndex] = queryParams[expandIndex] + "," + this._propertyName;
            }

            uriBuilder.Query = string.Join("&", queryParams);
            actionContext.Request.RequestUri = uriBuilder.Uri;
        }

    }
    #endregion
}

我以这种方式在我的控制器中使用:

Which I use in my controller in this way:

    [ExpandableProperty("Documents", false)]
    public IQueryable<ClientActivity> GetAllClientActivities()
    {
        return Query(); 
    }

这篇关于Azure移动服务TableController不返回内部对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆