3

I have a request DTO like so:

[Route("/appusers/resetpwd/{UserId}", "PUT")]
public class ResetPassword : IReturn<AppUserDto>
{
    public Guid UserId { get; set; }
    public string OldPassword { get; set; }
    public string NewPassword { get; set; }

    public ResetPassword(Guid userId, string oldPassword, string newPassword)
    {
        UserId = userId;
        OldPassword = oldPassword;
        NewPassword = newPassword;
    }
}

The metadata page shows the three properties as REQUIRED = No in the list. Can they be made required? Or does this simply mean I have to check them on the server and throw an exception as is explained in the wiki?

ThommyB
  • 1,456
  • 16
  • 34

1 Answers1

2

You can declare required fields using ServiceStack's built-in ValidationFeature, e.g:

Enable in AppHost with:

Plugins.Add(new ValidationFeature());

//Register All Validators in Assembly
container.RegisterValidators(typeof(MyValidator).Assembly);

Configure with:

public class ResetPasswordValidator : AbstractValidator<ResetPassword>
{
    public ResetPasswordValidator()
    {
        RuleFor(x => x.UserId).NotEmpty();
        RuleFor(x => x.OldPassword).NotEmpty();
        RuleFor(x => x.NewPassword).NotEmpty();
    }
}

Designing Message-based and HTTP APIs

Note some serializers require all DTO's to have a parameterless constructor. Also Resetting a Users Password isn't a valid PUT Operation which is expected to be idempotent and roughly translates to "PUT this resource at this location", it's more appropriately sent as a POST.

You can find some tips on designing message-based and HTTP APIs in ServiceStack in this previous answer where I would rewrite this Request DTO as:

[Route("/users/{UserId}/reset-password", "POST")]
public class ResetPassword : IReturn<ResetPasswordResponse>
{
    public Guid UserId { get; set; }
    public string OldPassword { get; set; }
    public string NewPassword { get; set; }
}

Although if this Service doesn't need to return a response it can also just return void, e.g:

public class ResetPassword : IReturnVoid { ... }

And implemented in your Service with:

public void Any(ResetPassword request) { ... }
Community
  • 1
  • 1
mythz
  • 141,670
  • 29
  • 246
  • 390
  • Thanks Demis, helpful tips like always. Just reading [this book](http://shop.oreilly.com/product/0636920021575.do) about REST API Design rules. It is a bit old but helps. Yes I added Validators yesterday (using Jeremy's FluentValidator already for quite some time) and I am just implementing a `NotEmptyGuidValidator` custom validator for the above use case. Just one thing: I had problems with async/await when using IReturnVoid with something like cannot convert void to Task or so... (Sorry don't remember the exact error) If I see this again, I post a new message. – ThommyB Oct 15 '16 at 07:57
  • @ThommyB Were you using the `SendOneWay()` Service Client API? – mythz Oct 15 '16 at 15:52
  • I don't think so, I guess it was a `PutAsync()`, but I can't currently find it. But I think I will get to this again and then I will post a new question here. – ThommyB Oct 15 '16 at 19:44