I have the following interface in my business layer
public interface IUserService
{
void CreateUser(User user);
List<User> FindUsersByName(string searchedString);
User GetUserById(int userId);
User GetUserByCredentials(string login, string password);
void UpdateUser(User user);
void UpdateUserPassword(int userId, string oldPassword, string newPassword);
}
Now I want to provide web API for this interface. As you can see this interface has multiple get
methods that return one item GetUserById
and GetUserByCredentials
, it also has multiple update methods UpdateUser
and UpdateUserPassword
, in future I might want to add additional get method that returns a collection, like, GetAllUsers
, for instance.
The obvious solution was to encapsulate this functionality in one controller.
So what I did first, in WebApiConfig
I changed routes configuration to
config.Routes.MapHttpRoute(
name: "DefaultApi",
//as you can see I added {action} to the path so that, it will be possible to differentiate between different get/put requests
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Then I created a UsersController
that looks like this
public class UsersController : ApiController
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
// POST api/users/createuser
[HttpPost]
public IHttpActionResult CreateUser(User user)
{
//some code
}
// GET api/users/getuserbyid?id=1
[HttpGet]
public IHttpActionResult GetUserById(int id)
{
//some code
}
// GET api/users/getuserbycredentials?login=log&password=pass
[HttpGet]
public IHttpActionResult GetUserByCredentials(string login, string password)
{
//some code
}
// GET api/users/findusersbyname?searchedString=jack
[HttpGet]
public IHttpActionResult FindUsersByName(string searchedString)
{
//some code
}
// PUT api/users/updateuser
[HttpPut]
public IHttpActionResult UpdateUser(UserBase user)
{
//some code
}
// PUT api/users/updateuserpassword?userId=1&oldPassword=123&newPassword=1234
[HttpPut]
public IHttpActionResult UpdateUserPassword(int userId, string oldPassword, string newPassword)
{
//some code
}
}
As you can see from the code above I have different URIs for each action method, e.g., for GetUserById
- api/users/getuserbyid?id=1
, for GetUserByCredentials
- api/users/getuserbycredentials?login=log&password=pass
and so on. This solution works fine so far, but the problem is, as far as I know you cannot have multiple gets according to REST, so does this solution still comply with the constraints for a RESTful service? And if not how can I make it truly RESTful? The idea of splitting this interface into different controllers seems a little odd to me, because in the future I may want to add some new methods to my interface, like, GetUsersByGender
, GetUsersByDateOfBirthday
and so on (if I'm going to create a new controller each time, that doesn't sound right to me)