本周我获准学习ServiceStack。我喜欢它。这是一个了不起的框架。但是我遇到了一个我无法得到一个相当直接的例子来工作的情况。 (虽然它确实不像示例那样简单,但可能更为现实。)
为这个长期问题提前道歉。
我有一个简单的DTO映射到这样的数据库......
[Description("Customer")]
[Alias("Customers")]
public class Customer : IHasId<int>
{
[Alias("Id")]
[AutoIncrement]
public int Id { get; set;}
[Required]
public int CompanyId { get; set;}
[Required]
public string FirstName { get; set;}
[Required]
public string LastName { get; set;}
public string MiddleInitial { get; set;}
public string EmployerName { get; set;}
public string ServiceLocationDescription { get; set;}
public string Street1 { get; set;}
public string Street2 { get; set;}
public string City { get; set;}
public string State { get; set;}
public string Zip { get; set;}
[Required]
public string Phone { get; set;}
public string Fax { get; set;}
[Required]
public string EmailAddress { get; set;}
}
}
我还创建了看起来像这样的请求DTO ......
//request dto
[Route("/customers/{companyId/customer/{customerId}", "GET")]
public class GetCustomer : Customer
{
}
[Route("/customers/{companyId}/customer/{customerId}", "PUT")]
public class UpdateCustomer : Customer
{
}
我意识到路线是一样的...这可能是问题......但我指的是不同的http方法....
最后我有一个看起来像这样的服务......
public CustomerResponse Get(GetCustomer request)
{
return new CustomerResponse { Customer = customerRepository.GetCustomer(request.CustomerId), };
}
public object Put(UpdateCustomer request)
{
customerRepository.UpdateCustomer(request);
return new HttpResult
{
StatusCode = HttpStatusCode.NoContent,
Headers = {
{ HttpHeaders.Location, this.RequestContext.AbsoluteUri.CombineWith(request.Id.ToString()) }
}
};
}
所以为了测试它,我创建了以下简单的html ...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="en-us" http-equiv="Content-Language" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
</head>
<body>
<form action="http://localhost:8080/co/1/customers/1000" method="get">
<br />
<label id="Label1">CompanyId
<input name="CompanyId" type="text" /></label><br />
FirstName
<input name="FirstName" type="text" /><br />
LastName
<input name="LastName" type="text" /><br />
Middle Initial
**OTHER FIELDS**
<input type="submit" />
</form>
</body>
</html>
所有这一切都很有效,只有PUT路由到GET服务。
我的目标是使用新值更新客户行。
我没有展示客户存储库类,但是工作正常。我猜。我有一个具体的一般问题。
如何在不使用GET的情况下路由到PUT。是否有使用该服务进行更新的“最佳实践”。例如......如果PUT服务不接收客户对象而是所有值......那么repo代码会获取记录并执行udpate吗?
POST方法(未显示)效果很好BTW。它与PUT方法完全相同(收到Customer对象等)
修改
我还确定我尝试使用DELETE http方法也会路由到GET。这是一种甚至不从Customer继承的简单类型。它只获得两个删除参数。现在我真的很困惑。
编辑2
似乎只是路由到返回具体类型的服务方法。返回对象的POST是例外... Get返回客户响应对象。获取客户返回客户(复数)响应对象并起作用。其余的服务方法是返回对象。是吗?
答案 0 :(得分:8)
浏览器不支持PUT / DELETE,正如Eli指出的那样。应该能够使用X-HTTP-Method-Override
作为输入字段使其与ServiceStack一起使用。 @mythz偷走了我的雷声并增加了对它的支持here(对他的殴打并不痛苦)
此外,您的<form>
方法是'get',它应始终路由到ServiceStack的服务'Get'方法。
未经测试,但我认为这应该有效。
<form action="http://localhost:8080/co/1/customers/1000" method="POST">
<br />
<input name="X-HTTP-Method-Override" type="hidden" value="PUT" />
<label id="Label1">CompanyId
<input name="CompanyId" type="text" /></label><br />
FirstName
<input name="FirstName" type="text" /><br />
LastName
<input name="LastName" type="text" /><br />
Middle Initial
**OTHER FIELDS**
<input type="submit" />
</form>