Reputation: 1536
I'm currently struggling to get inheritance in WebApi working like I'd like to. Maybe you can point me in the right direction?
My goal is to have a generic WebApi project, which can be reused in multiple other WebApi projects.
For example: I have a reusable UserController which can handle the login for multiple WebSites. Now I build a new WebSite and simple add the UserController to the newly created project, which simply works.
But now the requirement for the new WebSite changes and I need to overload the UserController methods to reflect these changes without modifying the generic controller.
What I want to achieve can be seen in the following code snippet (of course this won't compile because C# complains not suitable method to overload found.)
// This belongs to solution "GenericWebApi"
public class LoginRequest
{
public string User { get; set; }
}
public class BaseApiController : ApiController
{
[Route("login")]
public virtual HttpResponseMessage Login(LoginRequest request)
{
return new HttpResponseMessage();
}
}
// This belongs to solution "CarWebsite"
public class CarWebsiteLoginRequest : LoginRequest
{
public string Car { get; set; }
}
[RoutePrefix("api/users")]
public class CarWebsiteApiController : BaseApiController
{
public override HttpResponseMessage Login(CarWebsiteLoginRequest request)
{
// Do some car specific login stuff
return base.Login(request);
}
}
One solution I found to be working was replacing the "LoginRequest" and "CarWebsiteLoginRequest" with "dynamic", but that feels simply wrong and the ModelBinder of course will not work as intended.
Any ideas how you would solve that?
Thanks in advance
Upvotes: 3
Views: 15834
Reputation: 2896
If you pull out the variable and read it inside the method it is easier to overload
/// <summary>
/// Notice name is not Controller.cs This would expose this API if the name ended in controller
/// </summary>
public class GenericControllerApi : ApiController
{
protected JavaScriptSerializer JsonReader = new JavaScriptSerializer();
[HttpPost]
public virtual HttpResponseMessage Login()
{
string JsonRequest = Request.Content.ReadAsStringAsync().Result;
LoginRequest JSONData = null;
try
{
JSONData = (LoginRequest)JsonReader.Deserialize(JsonRequest, typeof(LoginRequest));
}
catch { }
if (JSONData != null)
{
if (CommonUserCalls(JSONData.User))
{
ShowUser UserReturn = new ShowUser();
UserReturn.UserName = "BaseUser";
return Request.CreateResponse(HttpStatusCode.OK, UserReturn);
}
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid User");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "ShowUser not provided");
}
}
protected bool CommonUserCalls(string User)
{
if (User == "MyUser")
{
return true;
}
return false;
}
public class LoginRequest
{
public string User { get; set; }
}
protected class ShowUser
{
public string UserName { get; set; }
}
}
public class CarController : GenericControllerApi
{
[HttpPost]
public override HttpResponseMessage Login()
{
string JsonRequest = Request.Content.ReadAsStringAsync().Result;
CarWebsiteLoginRequest JSONData = null;
try
{
JSONData = (CarWebsiteLoginRequest)JsonReader.Deserialize(JsonRequest, typeof(CarWebsiteLoginRequest));
}
catch { }
if (JSONData != null)
{
if (CommonUserCalls(JSONData.User))
{
ShowUser UserReturn = new ShowUser();
UserReturn.UserName = "CarUser";
return Request.CreateResponse(HttpStatusCode.OK, UserReturn);
}
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid User");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "CarWebsiteLoginRequest not provided");
}
}
public class CarWebsiteLoginRequest : LoginRequest
{
public string Car { get; set; }
}
}
Assuming you are reading/sending JSON
Upvotes: 0
Reputation: 5899
You can make your BaseApiController
generic:
public class BaseApiController<TLoginRequest> : ApiController
where TLoginRequest : LoginRequest
{
[Route("login")]
public virtual HttpResponseMessage Login(TLoginRequest request)
{
return new HttpResponseMessage();
}
}
And make your CarWebsiteApiController
use CarWebsiteLoginRequest
as a generic parameter:
public class CarWebsiteApiController : BaseApiController<CarWebsiteLoginRequest>
{
public override HttpResponseMessage Login(CarWebsiteLoginRequest request)
{
// Do some car specific login stuff
return base.Login(request);
}
}
Upvotes: 7