I search about base controller in asp.net mvc 6 however there is no any source (as far as i check).So how can i add base controller in asp.net mvc and use services on constuctor method or create new methods in base controller or any idea in order to use anything like base controller?
Any help will be appreciated.
Thanks.
You can add base controller in the following way:
public class BaseController : Controller
{
public IService Service { get; }
public BaseController(IService service)
{
Service = service;
}
}
Then, you can create your own controller and inherit BaseController instead of Controller class.
public class NewController : BaseController
{
public NewController(IService service) : base(service)
{
}
public IActionResult NewAction()
{
var result = Service.ServiceMethod();
}
}
With Microsoft.Extensions.DependencyInjection name space gives us access to the following extension method HttpContext.RequestServices.GetService
Here’s the source code of our BaseController class
public abstract class BaseController<T> : Controller where T : BaseController<T>
{
private IService service;
protected IService _service => telemetryInitializer ?? (telemetryInitializer = HttpContext.RequestServices.GetService<West.TelemetryService.ITelemetryHelper>());
}
The OrderController class extends this abstract BaseController
public class OrderController : BaseController<OrderController>
{
private readonly IOrderManager _orderManager;
public OrderController(IOrderManager orderManager)
{
_orderManager = orderManager;
}
[HttpGet]
public string Get()
{
Logger.LogInformation("Hello World!");
return "Inside the Get method of OrderController";
}
}
Related
I am programming a Web API using ASP.NET Core in connection with a web application. I am looking for a way to call a method (for example methodCallableFromOtherControllers) from another controller without it being callable from the client (vus.js). Thanks in advance for the support!
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpPost]
[Route("get_test")]
public string get_test([FromBody] Test test)
{
}
public string methodCallableFromOtherControllers()
{
}
}
Pls allow me to add my ideas here to describe it clearly.
Let's assume that there're 2 controllers here: HomeController and HelloController
And this is my HelloController:
namespace WebApi_net5.Controllers
{
public class HelloController : ControllerBase
{
[HttpGet("getHello")]
public string Index()
{
return "hello";
}
}
}
If I wanna call this Index() method from HomeController, I provide these 2 ways:
public class HomeController : ControllerBase
{
[HttpGet("test")]
public string test() {
var controller = new HelloController();
string temp = controller.Index();
return "a"+ temp;
}
}
Or using AddControllersAsServices() in startup.cs
public class HomeController : ControllerBase
{
private HelloController _controller;
public HomeController(HelloController controller) {
_controller = controller;
}
[HttpGet("test")]
public string test() {
string temp = _controller.Index();
return "a"+ temp;
}
}
startup.cs ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
//services.AddControllers();
services.AddControllers().AddControllersAsServices();
}
I have a requirement to have 2 data api's both of which should have same methods or endpoints to be implemented.
For example, we can have an interface to make sure, two classes will have same functions. Otherworldly, you define the contract.
public interface ITest
{
void Foo();
}
public class Test : ITest
{
public void Foo()
{
// Some logic
}
}
public class OtherTest : ITest
{
public void Foo()
{
// Some other logic
}
}
Similarly, I want controllers which will have routes and methods like below. Say in one a new action is added, the code should enforce it in the other controller.
DemoController
-- GET demo/api/action1
-- GET demo/api/action2
TestController
-- GET test/api/action1
-- GET test/api/action2
How to achieve this?
Well, you've sort of answered your own question, really. If you want to ensure that the same methods are implemented on multiple classes, that is what interfaces are for. You just make each controller implement the same interface and you're good to go.
As for ensuring a similar routing structure, you can use inheritance for that. Define a base abstract controller class. You can either choose to implement your interface here, and "implement" the required methods as abstract. Any derived class will be forced to implement any abstract methods on the base class, so it has the same effect as an interface. That technically means you can forgo the interface, if you want, and just rely on the base class forcing the implementation. Up to you. Then you can apply route attributes to your abstract methods like so:
[Route("[controller]/api")]
public abstract BaseApiController : ControllerBase
{
[HttpGet("action1")]
public abstract IActionResult Action1();
[HttpGet("action2")]
public abstract IActionResult Action2();
}
if you are dealing with different entities that requires similar business logic, you can create generic base controller and inject your common dependencies as well:
[Route("api/[controller]")]
[ApiController]
public class GenericBaseController<T> : ControllerBase where T : class
{
private readonly ILogger _logger;
public GenericBaseController(ILogger<GenericBaseController<T>> logger) {
_logger = logger;
}
[HttpGet("get")]
public IActionResult Get()
{
//...
}
[HttpPost("post")]
public IActionResult Post(T value)
{
//...
}
}
then you can extend the generic controller :
[Route("api/[controller]")]
[ApiController]
public class MyFirstController : MyFirstController<FirstModel>
{
public GenericBaseController(ILogger<MyFirstController> logger) : base(logger)
{
}
}
another one:
[Route("api/[controller]")]
[ApiController]
public class MySecondController : GenericBaseController<SecondModel>
{
public MySecondController(ILogger<MySecondController> logger) : base(logger)
{
}
}
You don't have to re-create the methods for each inherited controller if it is the same logic, or you may extend any of it if you need:
[Route("api/[controller]")]
[ApiController]
public class MyThirdController : GenericBaseController<ThirdModel>
{
public MyThirdController(ILogger<MyThirdController> logger) : base(logger)
{
}
[HttpPost("post")]
public IActionResult Post(ThirdModel value)
{
// do some logic...
return base.Post(value);
}
}
I have a web service in my project that I use to return json data to ajax calls.
Injecting my ClientService works fine on regular pages but how do I get it to work in the Web Service?
NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IClientService>().To<ClientService>();
}
Default.aspx.cs: works!
public partial class _Default : System.Web.UI.Page
{
[Inject]
public IClientService clientService { get; set; }
MyWebservice.asmx: NullReferenceException (clientService is null)
public class MyWebService: System.Web.Services.WebService
{
[Inject]
public IClientService clientService { get; set; }
[WebMethod, ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public MyObject GetClients(int id)
{
var list = clientService.GetClients(id);
I have solved this problem. I changed MyWebService class to derive from Ninject.Web.WebServiceBase:
public class MyWebService: WebServiceBase
I run on the same problem. Took me a while to figure it out.
My solution to this problem is adding statatic Ninject instantiation of Kernel in Global.asax :
public class Global : NinjectHttpApplication
{
private static Ninject.IKernel kernel = new Ninject.StandardKernel();
protected override Ninject.IKernel CreateKernel()
{
//Business TI
kernel.Bind<IYourService>().To<YourService>();
return kernel;
}
}
What enables to get it directly from singleton(public) or which solution I choosed, by accesing NinjectHttpApplication's context :
//in webservice parameterless constructor
yourService = ((NinjectHttpApplication)HttpContext.Current.ApplicationInstance).Kernel.Get<IPublicationService>();
This is the solution for working with legacy asmx web service, putting aside
I have problem with Abstract Factory pattern implementation on Spring. I am using Spring 3 MVC and Hibernate 3, which works fine if I don't use Abstract Factory Method pattern.
I am not sure what I have to add to the Controller to have access the Factory Class (CategoryFactory).
Is there anything missing in the Controller or bean initiating ?
class SectionsController extends MultiActionController {
/* Do I have to initiate the CategoryFactory here? */
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type = CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList", CategoryFactory.findCategory(type).list(id));
return new ModelAndView("Form", modelMap);
}
}
Abstract Factory
public abstract class Category {
public abstract List list(int departId);
}
public class CategoryFactory {
public enum CategoryType { firstclass, secondClass, ... }
public static Category findCategory(CategoryType categoryType) {
// Create type specific Category implementation
}
}
It shoud be:
class SectionsController extends MultiActionController {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type=CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList",CategoryFactory.findCategory(type).list(hibernateTemplate,id);
return new ModelAndView("Form", modelMap);
}
}
I am trying to learn TDD/BDD using NUnit and Moq.
The design that I have been following passes a DataService class to my controller to provide access to repositories.
I would like to Mock the DataService class to allow testing of the controllers.
There are lots of examples of mocking a repository passed to the controller but I can't work out how to mock a DataService class in this
scenerio.
Could someone please explain how to implement this?
Here's a sample of the relevant code:
[Test]
public void Can_View_A_Single_Page_Of_Lists()
{
var dataService = new Mock<DataService>();
var controller = new ListsController(dataService);
...
}
namespace Services
{
public class DataService
{
private readonly IKeyedRepository<int, FavList> FavListRepository;
private readonly IUnitOfWork unitOfWork;
public FavListService FavLists { get; private set; }
public DataService(IKeyedRepository<int, FavList> FavListRepository,
IUnitOfWork unitOfWork)
{
this.FavListRepository = FavListRepository;
this.unitOfWork = unitOfWork;
FavLists = new FavListService(FavListRepository);
}
public void Commit()
{
unitOfWork.Commit();
}
}
}
namespace MyListsWebsite.Controllers
{
public class ListsController : Controller
{
private readonly DataService dataService;
public ListsController(DataService dataService)
{
this.dataService = dataService;
}
public ActionResult Index()
{
var myLists = dataService.FavLists.All().ToList();
return View(myLists);
}
}
}
Create an interface like this:
public interface DataService
{
FavListService FavLists { get; }
void Commit();
}
Make your DataService implement this interface and your controller should depend on this interface. Problem solved :)
EDIT: This line of code:
dataService.FavLists.All().ToList();
is breaking the law of demeter and will be a pain to unit test your service. Create a method like AllFavList() on your service instead of all these chain of calls, it will be easier to mock.
EDIT2: How to mock you get property
dataService.SetupGet(d => d.FavLists).Returns(your_variable);