1

I'm having problems with how to make a generic controller. I have Model that the id property can be type of string or int. When i want to Edit a model that id is int, i can't find the action resulting in an error, because i implemented a override method to public abstract ActionResult Edit(string id).

Exists a way to pass a generic parameter(string or int) that my route can be undertand?

public abstract class BaseController<T> : Controller
{
    //protected UnitOfWork unitOfWork = new           UnitOfWork(System.Web.HttpContext.Current.User.Identity.Name);        
    protected UnitOfWork unitOfWork = new UnitOfWork("");
    public abstract ActionResult List();
    public abstract ActionResult Index();
    public abstract ActionResult Details(string id);, 
    public abstract ActionResult CreateByModal();
    public abstract ActionResult Create();
    [HttpPost]
    [ValidateAntiForgeryToken]
    public abstract ActionResult Create(T entity);
    public abstract ActionResult Edit(string id);
    [HttpPost]
    [ValidateAntiForgeryToken]
    public abstract ActionResult Edit(T entity);       
    public abstract ActionResult Delete(string id);

    protected override void Dispose(bool disposing)
    {
        //db.Dispose();
        base.Dispose(disposing);
    }
}

 public class ModeloController : BaseController<Modelo>
{
    public override ActionResult Edit(string id)
    {
       //Here i have a int Id im my Model  and the error in my route
        Modelo modelo = unitOfWork.ModeloRepository.Find(id);
        if (modelo == null)
        {
            return HttpNotFound();
        }
        return PartialView("_Edit", modelo);
    }
}


public class GeneroController : BaseController<Genero>
{
    //Here i have a string Id im my Model 
    public override ActionResult Edit(string id)
    {
        Genero genero = unitOfWork.GeneroRepository.Find(id);
        if (genero == null)
        {
            return HttpNotFound();
        }
        return PartialView("_Edit", genero);
    }

}

2
  • You can use object id as the parameter Commented May 20, 2015 at 12:41
  • You should refactor this so that you can use IRepository<int> or IRepository<string> - or you will need to create a custom controller factory that is able to resolve the controller type you require. Commented May 20, 2015 at 12:42

2 Answers 2

2

One option would be to overload each method that has id as a parameter:

public abstract ActionResult Details(string id);
public abstract ActionResult Details(int id); 

Or to add a second generic parameter for the type of id:

public abstract class BaseController<T, U> : Controller
{
    public abstract ActionResult Details(U id);
    public abstract ActionResult Edit(U id);

Either way you're putting more responsibility of the caller to make sure the right types are used.

Sign up to request clarification or add additional context in comments.

1 Comment

The first option would require implementing overrides that may not be relevant to the overridden class. The second generic parameter doesn't require that. Unfortunately, as you say, without some additional plumbing there's no compiler help to ensure the parameters match.
1

You can add an additional generic type parameter to indicate your key type for the given class.

public abstract class AbstractController<TEntity, TId> : Controller
{
    // irrelevant stuff omitted
    public ActionResult Edit(TEntity id);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.