向 Web API 返回对象添加字段

12 浏览
0 Comments

向 Web API 返回对象添加字段

在控制器中,我以这种方式返回json:

[System.Web.Http.HttpGet]
public JsonResult GetData()
{
 return Json(new { success = true, msg = "", result = myObject},   JsonRequestBehavior.AllowGet);
}

由于extjs期望成功消息作为json的一部分,我不得不在每个响应中添加这个,以及通常添加到结果中的所有数据对象。

现在我有了web api。在这里,您必须将某些方法的返回类型定义为对象,并基于接受头,结果将为json或xml(由于IE不发送该头,我遇到了很多问题,而且我总是得到xml作为返回 - 但我通过配置格式器解决了这个问题):

public myObject GetData(){
...
return myObject;
}

它能工作。但现在返回的json中没有{success = true, msg = ""}。

如何添加它以便以与控制器相同的方式返回?

(不使用自定义HttpContent类,因为它是丑陋的解决方法)。

最后,使用web api是否有意义,而不是使用mvc控制器-老方法?

存在接受头的问题,测试更困难(我必须模拟ajax调用,而使用控制器只需要调用url),而且似乎更麻烦才能获得适当的json。

我认为web api的唯一好处是根据接受头获取不同的序列化到客户端,但实际上没有必要获取除json之外的其他数据(至少我不需要)。那么,为什么不使用mvc控制器而不是web api呢?

0
0 Comments

问题的出现原因:

在Web API中,设计的初衷是在出现失败时返回HTTP状态码,并在响应中包含消息。这样,调用方就能知道如果收到状态码200(默认为Ok),则表示服务器上的处理都正确,否则需要处理HTTP状态码并对消息或响应对象进行处理。这种模式可以避免在所有响应中都添加"success"和"message"属性。同时,它还允许使用Action Filters来捕获一些常见的验证,如使用Authorize过滤器属性进行授权检查。

解决方法:

可以使用内置方法来处理常见的响应情况。通过创建一些扩展方法,可以将响应包装为通用的响应对象,而无需手动添加。下面是一些示例代码,可以动态创建通用响应对象:

public class TestController : ApiController
{
    [HttpGet]
    public IHttpActionResult Get()
    {
        var success = false;
        try
        {
            var someResult = new SomeObject() {Name = "igor"};
            // do something
            if (success)
                return this.Ok(new SomeObject() {Name = "igor"}); // 发送成功
            return this.Failure(someResult, "some known error"); // 发送带有部分对象的失败(如果可能)
        }
        catch (Exception ex)
        {
            return this.Failure("Something bad happened"); // 发送没有对象的失败,因为无法创建对象
        }
    }
}
public static class ApiControllerExtensions
{
    public static OkNegotiatedContentResult> Ok(this ApiController controller, T content)
    {
        return new OkNegotiatedContentResult>(new ResultWrapper() { Result = content, Success = true, Message = null }, controller);
    }
    public static OkNegotiatedContentResult> Failure(this ApiController controller, T content, string message)
    {
        return new OkNegotiatedContentResult>(new ResultWrapper() { Result = content, Success = false, Message = message }, controller);
    }
    public static OkNegotiatedContentResult Failure(this ApiController controller, string message)
    {
        return new OkNegotiatedContentResult(new FailureResult() { Success = false, Message = message }, controller);
    }
}
public class ResultWrapper
{
    public T Result { get; set; }
    public string Message { get; set; }
    public bool Success { get; set; }
}
public class FailureResult
{
    public string Message { get; set; }
    public bool Success { get; set; }
}
public class SomeObject
{
    public string Name { get; set; }
}

根据最新的评论,可以使用一些代码来动态创建通用的响应对象,而无需手动包装所有内容。通过创建一些扩展方法,可以将响应包装为通用的响应对象,而无需手动添加。可以使用这些扩展方法来实现只对具有特定请求参数(如"ext=1")的请求使用通用响应对象。

public class TestController : ApiController
{
    [HttpGet]
    public IHttpActionResult Get()
    {
        var success = false;
        try
        {
            var someResult = new SomeObject() {Name = "igor"};
            // do something
            if (success)
                return this.Ok(new SomeObject() {Name = "igor"}); // 发送成功
            return this.Failure(someResult, "some known error"); // 发送带有部分对象的失败(如果可能)
        }
        catch (Exception ex)
        {
            return this.Failure("Something bad happened"); // 发送没有对象的失败,因为无法创建对象
        }
    }
}
public static class ApiControllerExtensions
{
    public static OkNegotiatedContentResult> Ok(this ApiController controller, T content)
    {
        return new OkNegotiatedContentResult>(new ResultWrapper() { Result = content, Success = true, Message = null }, controller);
    }
    public static OkNegotiatedContentResult> Failure(this ApiController controller, T content, string message)
    {
        return new OkNegotiatedContentResult>(new ResultWrapper() { Result = content, Success = false, Message = message }, controller);
    }
    public static OkNegotiatedContentResult Failure(this ApiController controller, string message)
    {
        return new OkNegotiatedContentResult(new FailureResult() { Success = false, Message = message }, controller);
    }
}
public class ResultWrapper
{
    public T Result { get; set; }
    public string Message { get; set; }
    public bool Success { get; set; }
}
public class FailureResult
{
    public string Message { get; set; }
    public bool Success { get; set; }
}
public class SomeObject
{
    public string Name { get; set; }
}

如果希望只对具有特定请求参数(如"ext=1")的请求使用通用响应对象,可以修改扩展方法的实现。

0
0 Comments

问题的出现原因:需要给Web API返回对象添加字段。

解决方法:创建一个名为ResultBase的类,并按照下面的方式更改控制器代码。

class ResultBase {
    public bool success {get;set;}
    public string msg {get;set;}
    public T result {get;set;}
}
public ResultBase GetData(){
    ...
    return new ResultBase{success = true, msg = "", result = myObject};
}

非常感谢,这正是我想要的。

很高兴能帮到您,我可以将我的回答标记为正确答案吗?

0