Может ли служба ServiceStack содержать несколько методов?

Среда - это Visual Studio 2012, ServiceStack, проект веб-приложений ASP.NET(после https://github.com/ServiceStack/ServiceStack/wiki/Create-your-first-webservice)

Просматривая некоторые из классов в ServiceStack.Examples, я заметил, что большинство сервисов содержит только один метод. Либо некоторое переопределение на Execute(), либо, если служба REST, некоторое переопределение OnPost/Get/Put/Delete().

Как мне подойти к созданию полного набора API, если у меня есть десятки функций, которые мне нужны, чтобы реализовать RegisterUser(), RemoveUser(), AddFriend(), RemoveFriend()... Одна услуга за метод?

public RegisterUserService : IService<User> { public object Execute(User> dto) { ... } }
public RemoveUserService : IService<User> { public object Execute(User> dto) { ... } }
public AddFriendService : IService<Friend> { public object Execute(Friend dto) { ... } }
public RemoveFriendService: IService<RequestDTO4> { public object Execute(Friend dto) { ... } }

Я довольно потерял, как начать реализацию полного набора API. Я прочитал first и второй wiki на странице "Создание вашего первого веб-сервиса", который я скопировал, чтобы сделать 1 метод обслуживания. Но теперь я хочу сделать 10 или 40 методов обслуживания, и я не уверен, как это сделать.

Я заметил, что реализация из IRestService<T> позволяет использовать до 4 методов вместо одного метода Execute(), просто потому, что каждый метод соответствует другому HTTP-глаголу. Так что я могу написать? В основном что-то вроде:

public MyService : IService/IRestService/ServiceBase?<User>
{
     public object AddUser(User user) { }
     public object RemoveUser(User user) { }
     public object ModifyUser(User user) { }
}

Просто ищем что-то, что необязательно должно содержать все методы в одном классе сервиса, но насколько это возможно... действительно ли мне нужно создать 1 сервис для каждого метода службы?

Примечание о преследовании строго архитектуры RESTful: я только немного читал о REST, но мне кажется, что я должен строго следовать правилам, например: рассматривать все как ресурс, даже если вам нужно перепроектировать свои модели, нет глаголов в именах URL-адресов (/Friends, not/GetFriends, потому что REST дает вам OnGet(), OnPost(), OnPut() и OnDelete()... в основном меня интересуют самые простые, быстрые и безболезненные способ реализации нескольких десятков методов обслуживания. Это персональный проект, поэтому требования не будут сильно отличаться.

Заранее благодарим меня за этот первый шаг.

EDIT: только что увидел этот связанный вопрос: Как отправить команды с помощью ServiceStack?

Mythz сказал, что нет "пути ServiceStack" для разработки. Вопрос парня очень похож на мой. Мне интересно, как уложить множество сервисных методов в службу.

РЕДАКТИРОВАТЬ 2: Просто увидел Нужна помощь по внедрению servicestack и Отдельные или комбинированные сервисы ServiceStack?.

Я успешно проверил код ниже с рабочими маршрутами:

[Route("/registerUser/setEmail/{Email}")]
[Route("/registerUser/setPassword/{Password}")]
[Route("/registerUser/setPhoneNumber/{PhoneNumber}")]
[Route("/lalal2395823")]
[Route("/test3234/test23423511")]
public class RegisterUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Nickname { get; set; }
    public string PhoneNumber { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

Но то, что мне нужно, это для каждого [Route("path")] перейти к другому методу, вместо того, чтобы все они проанализировали в Execute() и должны были проанализировать, какая строка не является нулевой или пустой.


Мое решение

Я решил взять совет Рикарда и сделать правильный REST API, потому что в конце он кажется более простым и чистым.

Теперь это мой класс, используя новый ServiceStack API (новый от 9/24/12):

using UserModel = Project.Model.Entities.User;

[Route("/User", "POST")]
[Route("/User/{FirstName}", "POST")]
[Route("/User/{FirstName}/{LastName}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}/{PhoneNumber}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}/{PhoneNumber}/{Email}", "POST")]
public class CreateUser : IReturn<UserModel>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Nickname { get; set; }
    public string PhoneNumber { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

public class CreateUserService : Service
{
   public object Post(CreateUser request)
    {
        try
        {
            using (var session = FluentNHibernateHelper.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    var user = new UserModel()
                    {
                        FirstName = request.FirstName,
                        LastName = request.LastName,
                        Nickname = request.Nickname,
                        PhoneNumber = request.PhoneNumber,
                        Email = request.Email,
                        Password = request.Password,
                    };
                    session.SaveOrUpdate(user);
                    transaction.Commit();

                    return user;
                }
            }
        }
        catch
        {
            throw;
        }
    }
}

Ответ 1

Следуя HTTP-способу, вы должны перевернуть свой образ мышления с ног на голову. Вам нужно подумать о ресурсах, то есть о пользователях, друзьях и т.д. Используя HTTP, вы уже имеете конечный набор методов, а именно Get, Put, Post и Delete.

Следовательно, дизайн API службы может выглядеть следующим образом:

RegisterUser() => POST /users
RemoveUser() => DELETE /users/{userid}
AddFriend() => POST /users/{userid}/friends
RemoveFriend() => DELETE /users/{userid}/friends/{friendid}
ModifyUser() => PUT /users/{userid}

и др.

Чтобы реализовать, например, RemoveFriend в ServiceStack, вы можете сделать следующее:

public class UserFriendService : RestServiceBase<UserFriendRequest>
{
    public override object OnPost(UserFriendRequest request)
    {
        // pseudo code 
        var user = GetUser(request.UserId);
        var friend = GetUser(request.FriendId); // FriendId is a field in the HTTP body
        user.Friends.Add(friend);
        return HttpResult.Status201Created(user, ...);
    }
    //...
}

[Route("/users/{userId}/friends")]
public class UserFriendRequest
{
    public string UserId { get; set; }
    public string FriendId { get; set; }
}

Ответ 2

Теперь это намного проще с ServiceStack new API Design, выпущенным в (v3.9.15 +).

@Рикард делает много хороших моментов в том, как переструктурировать ваш сервис, поэтому он больше REST-ful, который теперь легче достичь с помощью нового API ServiceStack, который теперь менее ограничительный и более гибкий, когда одна и та же служба может обрабатывать несколько разные запросы DTO, и вы больше не ограничены в типе ответа, который вы можете вернуть.