在OpenRasta处理程序中处理HTTP PUT时,我遇到了一些非常奇怪的行为。处理程序方法签名如下所示:
public CustomerResource Put(CustomerForm customerForm)
以下是相关的ResourceSpace
配置:
ResourceSpace.Has.ResourcesOfType<CustomerListResource>()
.AtUri("/customers")
.HandledBy<CustomerHandler>()
.RenderedByAspx("~/Views/Customer/CustomerListView.aspx")
.And.AsJsonDataContract().ForMediaType("application/json;q=0.3")
.And.AsXmlSerializer().ForMediaType("application/xml;q=0.2");
ResourceSpace.Has.ResourcesOfType<CustomerResource>()
.AtUri("/customers/{id}")
.HandledBy<CustomerHandler>()
.RenderedByAspx("~/Views/Customer/CustomerEditView.aspx")
.And.AsJsonDataContract().ForMediaType("application/json;q=0.3")
.And.AsXmlSerializer().ForMediaType("application/xml;q=0.2");
// To support POST and PUT to /customers
ResourceSpace.Has.ResourcesOfType<CustomerForm>()
.WithoutUri
.RenderedByAspx("~/Views/Customer/CustomerEditView.aspx")
.And.AsJsonDataContract().ForMediaType("application/json;q=0.3")
.And.AsXmlSerializer().ForMediaType("application/xml;q=0.2");
CustomerForm
看起来像这样:
[XmlRoot("customer", Namespace = ClientSettings.Namespace)]
public class CustomerForm : FormBase, ICustomer
{
[XmlElement("contact-info")]
public ContactInfo ContactInfo { get; set; }
[XmlAttribute("id")]
public int Id { get; set; }
}
ContactInfo
看起来像这样:
[XmlRoot("contact-info", Namespace = ClientSettings.Namespace)]
public class ContactInfo
{
[XmlElement("email")]
public string Email{ get; set; }
[XmlElement("first-name")]
public string FirstName{ get; set; }
[XmlElement("last-name")]
public string LastName{ get; set; }
[XmlElement("mobile-phone-number")]
public string MobilePhoneNumber { get; set; }
}
我的问题是当CustomerForm
PUT到服务器时,OpenRasta无法正确反序列化它。它的作用是将ContactInfo
设置为null
进行反序列化,尽管它是从客户端成功发送的。我甚至已经深入到IRequest.Entity.Stream
以确保我需要的XML确实存在,并且它是:
<?xml version="1.0" encoding="utf-8"?>
<customer id="1" xmlns="urn:namespace">
<contact-info>
<email>5867ca8a5a5548428c4bc90c1f7e41d6@example.com</email>
<first-name>0440a6d5f071478d8571bac1301552bc</first-name>
<last-name>49069fb41eb141c79326dc64fa034573</last-name>
<mobile-phone-number>59980075</mobile-phone-number>
</contact-info>
</customer>
如果IRequest.Entity.Stream
方法中收到的反序列化CustomerForm
对象没有,Put(CustomerForm)
如何包含必要的数据?我有测试确保序列化和反序列化完美地工作,我甚至在完全相同的处理程序中也有Post(CustomerForm)
。只有当HTTP方法为PUT时CustomerForm
将ContactInfo
设置为null
。
我已经彻底阅读了OpenRasta的调试输出,所有内容都是:
27-[2011-07-15 11:09:15Z] Information(0) Operation CustomerHandler::Put(CustomerForm customerForm) was selected with a codec score of 0
27-[2011-07-15 11:09:15Z] Information(0) Loaded codec OpenRasta.Codecs.XmlSerializerCodec
27-[2011-07-15 11:09:15Z] Verbose(0) Switching to full object media type reading.
27-[2011-07-15 11:09:15Z] Stop(1) Exiting PipelineRunner
27-[2011-07-15 11:09:15Z] Start(1) Entering PipelineRunner: Executing contributor OperationInterceptorContributor.WrapOperations
27-[2011-07-15 11:09:16Z] Stop(1) Exiting PipelineRunner
27-[2011-07-15 11:09:16Z] Start(1) Entering PipelineRunner: Executing contributor OperationInvokerContributor.ExecuteOperations
27-[2011-07-15 11:09:16Z] Verbose(0) Ignoring constructor, following dependencies didn't have a registration:OpenRasta.OperationModel.Interceptors.IOperationInterceptor[]
我发现的唯一奇怪的是,MissingMethodException
在此步骤之后被抛出为FirstChanceException
(但从未冒泡),但它的堆栈痕迹太短了我不知道可能是什么问题:
2011-07-15T13:09:16.036 AppDomain.FirstChanceException
System.MissingMethodException: Member not found.
at System.DefaultBinder.BindToMethod(BindingFlags bindingAttr, MethodBase[] match, Object[]& args, ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, Object& state)
我不知道为什么会抛出MissingMethodException
以及为什么在我不订阅AppDomain.FirstChanceException
事件时它不会冒泡,但这可能与我{{1}的原因有关没有正确反序列化。但是,由于它在HTTP POST上正确反序列化,我有疑虑。
想法?
答案 0 :(得分:1)
听起来很古怪,但您是否尝试将ID移至CustomerForm对象的顶部?
[XmlRoot("customer", Namespace = ClientSettings.Namespace)]
public class CustomerForm : FormBase, ICustomer
{
[XmlAttribute("id")]
public int Id { get; set; }
[XmlElement("contact-info")]
public ContactInfo ContactInfo { get; set; }
}
Openrasta使用(可怕的).net数据契约xml序列化程序,它对元素位置很敏感。我们实际上编写了我们自己的序列化器,它只是恢复到传统的'dot net'xml序列化器。
答案 1 :(得分:1)
问题似乎在于如何解释URL并将其映射到处理程序,因为如果我添加一个也需要int id
的处理程序方法,如下所示:
CustomerResource Put(int id, CustomerForm customerForm)
有效。这可能是由于以下资源注册:
ResourceSpace.Has.ResourcesOfType<CustomerResource>()
.AtUri("/customers/{id}")
虽然我有这个:
ResourceSpace.Has.ResourcesOfType<CustomerForm>()
.WithoutUri
我尝试修改CustomerForm
的注册以包含ID:
ResourceSpace.Has.ResourcesOfType<CustomerForm>()
.AtUri("/customers/{id}")
并且还要在CustomerResource
和CustomerForm
注册中选择ID:
ResourceSpace.Has.ResourcesOfType<CustomerResource>()
.AtUri("/customers/{*id}")
ResourceSpace.Has.ResourcesOfType<CustomerForm>()
.AtUri("/customers/{*id}")
这没有任何帮助,但将int id
参数添加到处理程序方法中,所以我很高兴因为这使OpenRasta成功反序列化我的实体。