Asp.net 5 个网站 api 自定义 ActionResult

Asp.net 5 web api Custom ActionResult

这是我对自定义 ActionResult 的实现

public class ResultData<T>
{
    public string Code { get; set; }
    public string Massage { get; set; }
    public T Result { get; set; }
}

public class BaseApiResult<T> : JsonResult
{
    public BaseApiResult() : base(null)
    {
        ContentType = "application/json";
    }

    public IActionResult Success(T result)
    {
        Value = new ResultData<T>
        {
            Code = "2000",
            Massage = "Sucsess",
            Result = result
        };

        StatusCode = 200;
     
        return this;
    }

    public IActionResult Fail(T result, string code, string massage)
    {
        Value = new ResultData<T>
        {
            Code = code,
            Massage = massage,
            Result = result
        };

        StatusCode = 400;

        return this;
    }

    public IActionResult ServerError(T result)
    {
        Value = new ResultData<T>
        {
            Code = "5000",
            Massage = "Internal Server Error",
            Result = result
        };

        StatusCode = 500;
       
        return this;
    }
}

现在我们这样称呼它

    [HttpGet("GetProducts")]
    public IActionResult GetProducts()
    {
        try
        {
            var res = _entityFrameworkCoreService.GetAllProducts();

            if (res.Count <= 0)
            {
                return new BaseApiResult<string>().Fail(null, "4002", "NoRecord found");
            }

            return new BaseApiResult<IList<DtoProSubCat>>().Sucsees(res); ;
        }
        catch (Exception ex)
        {
            return new BaseApiResult<string>().ServerError(ex.Message);
        }
    }

现在我要问的是:-

1- 这是 ActionResult 的错误实现吗?

2- 此实现是否存在性能问题?

3- 是否有任何增强功能可以添加到此实现中?

3- 实现自定义 ActionResult 的最佳实践是什么?

上面的方法还是可以的,但是个人觉得不太好。 首先,您真正需要的是 return 包裹在 ResultData 中的结果。 这被认为是一种数据模型,而不是一种行为。要知道,IActionResult不仅仅是return数据,在AspMVC运行模型中,它也是HTTP服务器的输出处理程序。

我提出以下几种方案,相信会更适合。

方法一:为ControllerBase创建一个基础class。 例如:

public class ControllerBase : Microsoft.AspNetCore.Mvc.Controller
{
    protected IActionResult MyResult <T> (int statusCode, ResultData<T> result)
    {
        var jsonResult = Json(result);
        jsonResult.StatusCode = statusCode;
        return jsonResult;
    }

    protected IActionResult Success <T> (T result)
    {
        return MyResult(200, new ResultData<T>
        {
            Code = "2000",
            Massage = "Sucsess",
            Result = result
        });
    }

    protected IActionResult Fail <T> (T result, string code, string massage)
    {
        return MyResult(400, new ResultData<T>
        {
            Code = code,
            Massage = massage,
            Result = result
        });
    }

    protected IActionResult ServerError<T>(T result)
    {
        return MyResult(500, new ResultData<T>
        {
            Code = "5000",
            Massage = "Internal Server Error",
            Result = result
        });
    }
}

/** implement */
public class HomeController : ControllerBase
{
    [HttpGet("GetProducts")]
    public IActionResult GetProducts()
    {
        try
        {
            IList<DtoProSubCat> res = new List<DtoProSubCat>() { new DtoProSubCat() }; //

            if (res.Count <= 0)
            {
                return Fail<string>(null, "4002", "NoRecord found");
            }

            return Success<IList<DtoProSubCat>>(res); ;
        }
        catch (Exception ex)
        {
            return ServerError(ex.Message);
        }
    }
}

有点类似的方法是为 Controller 创建一个扩展函数,或者您将创建一个包含处理数据的函数的静态 class。

方法二:为每个响应行为创建一个特定的class。 例如:

public class SuccessResult <T> : JsonResult
{
    public SuccessResult (T result)
        : base(new ResultData<T>
        {
            Code = "2000",
            Massage = "Sucsess",
            Result = result
        })
    {
        StatusCode = 200;
    }
}

public class FailResult<T> : JsonResult
{
    public FailResult(T result, string code, string massage)
        : base(new ResultData<T>
        {
            Code = code,
            Massage = massage,
            Result = result
        })
    {
        StatusCode = 400;
    }
}

public class ServerErrorResult<T> : JsonResult
{
    public ServerErrorResult(T result)
        : base(new ResultData<T>
        {
            Code = "5000",
            Massage = "Internal Server Error",
            Result = result
        })
    {
        StatusCode = 500;
    }
}

/** implement */
public class HomeController : Controller
{
    [HttpGet("GetProducts")]
    public IActionResult GetProducts()
    {
        try
        {
            IList<DtoProSubCat> res = new List<DtoProSubCat>() { new DtoProSubCat() }; //

            if (res.Count <= 0)
            {
                return new FailResult<string>(null, "4002", "NoRecord found");
            }

            return new SuccessResult<IList<DtoProSubCat>>(res); ;
        }
        catch (Exception ex)
        {
            return new ServerErrorResult<string>(ex.Message);
        }
    }
}

你上面的实现方式使得几行命令毫无意义,当然在应用程序的运行ning期间没有太大问题,但在长时间的运行中会影响扩展或维护过程。以上两种方式帮你保护函数的运行模型,最小化源代码,最小化无意义的命令行。

这个 V2 怎么样,因为 @Henry Trần 给出了提示

public class BaseApiResultV2
{
    private IActionResult SetResult<T>(int statusCode, ResultData<T> result)
    {
        JsonResult jsonResult = new(result)
        {
            StatusCode = statusCode,
            ContentType = "application/json"
        };

        return jsonResult;
    }

    public IActionResult Success<T>(T result)
    {
        return SetResult(StatusCodes.Status200OK,
            new ResultData<T>
            {
                Code = "2000",
                Massage = "Sucsess",
                Result = result
            });
    }

    public IActionResult Fail<T>(T result, string code, string massage)
    {
        return SetResult(StatusCodes.Status400BadRequest,
            new ResultData<T>
            {
                Code = code,
                Massage = massage,
                Result = result
            });
    }

    public IActionResult ServerError<T>(T result)
    {
        return SetResult(StatusCodes.Status500InternalServerError,
            new ResultData<T>
            {
                Code = "5000",
                Massage = "Internal Server Error",
                Result = result
            });
    }

    private struct ResultData<T>
    {
        public string Code { get; set; }
        public string Massage { get; set; }
        public T Result { get; set; }
    }
}