Here is my implementation of Custom 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;
}
}
Now this how we call it
[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);
}
}
Now what I what to ask about is: -
1- is this a wrong implementation of ActionResult ?
2- is this implementation have performance issues ?
3- is there any enhancement to add to this implementation ?
3- what is the best practice for Implementing Custom ActionResult ?
CodePudding user response:
The method above will still work fine, but personally I think it's not good. First of all, what you really need is to return the results wrapped in ResultData. This is considered a data model, rather than a behavior. It should be known that IActionResult is not just the return data, but in the Asp MVC operation model, it is also the output handler for the HTTP server.
I propose some of the following solutions, which I believe will be more suitable.
Method 1: Create a base class for ControllerBase. Eg:
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);
}
}
}
A somewhat similar way is to create an extensions functions for Controller or you will create a static class that contains functions that process data.
Method 2: Create a specific class for each response behavior. Eg:
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);
}
}
}
The way you implement the above makes a few lines of command pointless, of course during the running of the application there is not much problem, but in the long run will affect the expansion or maintenance process. The above two ways help you protect the operating model of the function, minimize the source code, and minimize the meaningless command lines.
CodePudding user response:
what about this V2 as @Henry Trần gives a hint about it
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; }
}
}