仅更新客户端

时间:2015-09-22 01:13:52

标签: c# servicestack

我有一个servicestack服务,它接受一个如下所示的DTO:

[Route("/appointment/{id}", Verbs = "POST")]
public class UpdateAppointment
{
    public Guid Id { get; set; }

    public DateTime StartTime { get; set; }

    public int Duration { get; set; }

    public string Description { get; set; }

    public Guid? MemberId { get; set; }
}

如何检查ClientId值是否由客户端设置,因为“null”是有效值。通常,如果NULL不是有效值,我可以使用PopulateWithNonDefaultValues()方法。

所以结果应该是如果我没有在HTTP POST有效负载中指定MemberId,我希望服务器不更新该值。

我希望这是有道理的。

3 个答案:

答案 0 :(得分:2)

如果您认为客户端在调用UpdateAppointment服务时始终提供所有值,则通常不会出现此问题。所以我强烈建议您考虑每个属性是客户端提供的“有效”值并更新所有字段。

如果只想更新部分属性列表,请创建单独的服务。

如果我真的需要检查客户端是否提供了值,您可以在Request DTO构造函数中指定不同的值,例如:

public class UpdateAppointment
{
    public UpdateAppointment() 
    {
        MemberId = Guid.Empty;
    } 
    //...
}

其中非Guid.Empty值表示它已由客户填充。

或者您也可以使用计算出的属性:

public class UpdateAppointment
{

    [IgnoreDataMember]
    public bool HasMemberId { get; set; }

    Guid? memberId;
    public Guid? MemberId 
    {
        get { return memberId; }
        set 
        {
            memberId = value;
            HasMemberId = true;
        }
    }
}

更脆弱的替代方法是使用全局请求过滤器缓冲请求:

appHost.PreRequestFilters.Add((httpReq, httpRes) => {
    httpReq.UseBufferedStream = true;
});

其中会保留一份请求流副本,您可以通过以下方式获取服务副本:

var jsonBody = base.Request.GetRawBody();
var hasMemberId = jsonBody.ToLower().Contains("memberid");

虽然注意这是依赖于序列化程序的,即不能使用像ProtoBuf或MsgPack这样的二进制序列化程序。

答案 1 :(得分:1)

如果不允许空值,为什么MemberId可以为空?

只需将其定义更改为:

public Guid MemberId { get; set; }

答案 2 :(得分:0)

您是否尝试先加载值,然后在更新前对其进行编辑?

我的意思是:

[HttpPost]
public ActionResult Update(UpdateAppointment UAForm){
     UpdateAppointment ua = new UpdateAppointmentBll().Find(UAForm.Id);
     ua.StartTime = UAForm.StartTime;
     //so no...
     if(UAForm.MemberId != null)
        ua.MemberId = UAForm.MemberId;

     new UpdateAppointmentBll().Save(ua);

     return View();
}