ardalis / Result

A result abstraction that can be mapped to HTTP response codes if needed.
MIT License
866 stars 107 forks source link

Improve error/validation reporting by allowing for a strongly typed property, e.g. Result.Error<T> #163

Open nhwilly opened 8 months ago

nhwilly commented 8 months ago

When calling downstream API's there are times when the consuming program needs the details of an error so that domain specific actions can be taken.

Example:

MyBlazorApp calls MyBlazorAppApi to add a user to a downstream service using a DownstreamApi wrapper, which makes the actual REST calls to the downstream service.

MyBlazorAppApi endpoint:

public async Task<IActionResult<MyBlazorUser>> AddMyBlazorUser(string email)
{
  Result<DownstreamUser> downstreamUserResult = await AddDownstreamUser(email);
  if(downstreamUserResult.IsSuccess)
    {
      return downStreamUserResult.Value.Map<MyBlazorUser>();
    }
}

DownstreamAPI wrapper function:

public async Task<Result<DownstreamUser>> AddDownstreamUser(string email)
  {
    // make httpClient calls here...
    // return success with downstreamUser
    // or deserialize errors to errorData and return Result.Error<ErrorData>(errorData);
  }

For example, DownstreamApi reports that the user already exists and returns a 400 bad request with a specific error code in the errorData that's returned. Other 400 errors are show stoppers, but this one is not. If I know the actual error code that the downstream api is sending me, I can discriminate and take the proper action.

Using Result.Error<T> (or possibly Result.Invalid<T>) allows me to return the errorData up to the AddMyBlazorUser endpoint where a second call can be made to find the existing user via their email address and return the MyBlazorUser instance to the MyBlazorApp original caller.

As it stands, I am using some special delimiters to embed their error message in the standard collection of strings and then looking for it in the caller. Working but it could be improved.

backendsamurai commented 1 month ago

@nhwilly I support you. Result.Error<T> is much needed function