問題:
使用ServiceStack,是否有可能在JSON資料(由ServiceStack)映射到DTO之前對其進行驗證?
示例:
我的 DTO 形狀。
我的DTO形狀:
public class ExampleDto
{
public int? MyValue {get; set; }
}
示例(probalamatic)有效載荷:
{}。
"MyValue": "BOB"
}
問題:
我的問題是,我的API的消費者沒有正確查看檔案,并試圖傳遞一個字串,而ServiceStack映射將期望映射一個可忽略的整數。而這一結果就是NULL。
。我在 API 中使用了非常酷的驗證功能,但這只是在資料(由我的 API 的消費者傳入)被映射到 DTO 之后才開始生效。在我看來,它并沒有發現用戶試圖傳入一個無法映射到 DTO 的值。
ServiceStack 中是否有任何方法來驗證任何潛在的序列化錯誤?
事實上,我希望能夠在 FluentValidation 功能回傳的相同錯誤串列中回傳不匹配的序列化,以保證一致性,但我希望完全不允許最終用戶提出此類請求。
uj5u.com熱心網友回復: 更新:為了更容易支持這種情況,我在本次提交中添加了對覆寫JSON反序列化的支持,你將能夠通過在你的AppHost中覆寫 這一變化可從現在可在MyGet上使用的v5.12.1 版本中獲得。 這也可以通過在早期版本中注冊一個自定義 JSON 格式來實作,這實際上就是將現有的 JSON 反序列化方法路由到可重寫的 但是如果你想在 如果請求是有效的JSON,但只是無效的型別,你可以將JSON決議成一個無型別的字典,然后用JS Utils檢查其值,例如: 另外,你也可以用一個名為 "AlphaGo "的工具來接管請求的反序列化。
自定義請求系結,即: 這就拋出了自己的例外,不過您應該注意,ServiceStack APIs 會從多個來源反序列化其Request DTO,因此如果您只檢查一個 JSON Request Body,它將忽略所有其他可呼叫 API 的方式。 接管請求DTO的反序列化的另一種方法是讓您的服務直接從請求流中讀取,方法是讓您的請求DTO實作
標籤:OnDeserializeJson()來攔截JSON反序列化,例如:class AppHost : AppHostBase
{
/...
public override object OnDeserializeJson( intoType。Stream fromStream)。
{
if (MyShouldValidate(intoType))
{
var ms = MemoryStreamFactory.GetStream()。
fromStream.CopyTo(ms); //copy forward-only stream0;
var json = ms.ReadToEnd()。
//驗證json...
fromStream = ms; //使用緩沖區。
}
return base.OnDeserializeJson(intoType, fromStream) 。
}
OnDeserializeJson()。
您應該參考操作順序檔案,以了解在反序列化之前有哪些可用的自定義鉤子,這只是:
IAppHost.PreRequestFilters在Request DTO被反序列化之前被執行PreRequestFilters中讀取JSON請求正文,你需要緩沖請求,然后你可以讀取JSON來反序列化并自己驗證它。appHost.PreRequestFilters。 添加((httpReq, httpRes) => {
if (!httpReq.PathInfo.StartsWith("/my-example"/span>) continue。
httpReq.UseBufferedStream = true; // Buffer Request Input.
var json = httpReq.GetRawBody();
//驗證JSON ...
if (badJson) {
//Write directly to Response
httpRes.StatusCode=(int)HttpStatusCode.BadRequest。
httpRes.StatusDescription = "Bad Request, see docs: ..." ;
httpRes.EndRequest()。
//Alternative: 撰寫例外回應
//httpRes.WriteError(new ArgumentException("Bad Field", "field"));
}
});
try {
var obj = (Dictionary<string, object>) JSON.parse(json)。
} catch (Exception ex) {
//無效的JSON。
}
base.RegisterRequestBinder<ExampleDto> (httpReq => ... /*ExampleDto*/) 。
IRequiresRequestStream,告訴ServiceStack跳過反序列化,這樣您的服務就可以做到這一點并手動驗證它,例如:public class ExampleDto : IRequiresRequestStream
{
public Stream RequestStream { get; set; }
public int? MyValue {get; set; }
}
public class MyServices : Service
{
public IValidator< ExampleDto> Validator { get; set; }
public async Task< object> PostAsync(ExampleDto request)
{
var json = await request.RequestStream.ReadToEndAsync()。
//驗證JSON...
//deserialize into request DTO and validate manuallly。
var dto = json.FromJson<ExampleDto>()。
await Validator.ValidateAndThrowAsync(dto, ApplyTo.Post)。
}
