Is it possible to add a .asmx file to an MVC project and have .asmx code call the controller and have the controller return data to the .asmx code?
Is it possible to add a .asmx file to
an MVC project
Yes.
asmx code call the controller and have
the controller return data to the
.asmx code?
Yes.
var controller = new YourController();
var httpContext = new HttpContextWrapper(this.Context);
var routeData = new RouteData();
var requestContext = new RequestContext(httpContext, routeData);
controller.ControllerContext = new ControllerContext(requestContext, controller);
var result = controller.YourAction();
But I discourage to do that. Instead move common logic into a separate service layer and use that one.
Unless you need functionality specific to the controller (such as rendered output, web context, etc), you could take out the logic you want to execute in the controller and put it in a new class and have both controller and webservice call the method in the new class.
You can call your asmx by adding an Ignore Route path in your global.asax RegisterRoute method
I can't answer the first part (though I assume it's possible), but the second part is simple.
It can of course access the controller because the controller is just a class with functions that return results. It will simply be a matter of setting the controller's HttpContext correctly, and then invoking the action method that you want. You can then do whatever you want with the ActionResult - render it to a string for instance.
Related
I am using MVC5 on ASP.NET 4.5
I want to debug specific Controller Actions without running the whole application where I would need to know how to navigate to the specific Action, in addition to it taking much time, since I have much code to refactor and test.
I have considered Unit Tests, but using the debugger seems more appropriate for what I am doing.
Also I have session variables within the Action Code.
The closest I have come to a solution is to have a wrapper Action in Home ie:
public ActionResult Tx()
{
return new MyApp.Areas.Area1.Controllers.OrderController().Index();
}
I would then copy and paste the relevant Namespace, Controller and Action with any relevant parms into the "Tx" Action.
This does invoke the relevant Action without me needing to navigate to the specific Action. I just call Home/Tx. However I am getting null exception errors with my Session variable code:
Session["OrderID"]=null
Debugging the Action, with the Session variables works fine when I navigate directly from the application. When I use Home/Tx it is still on the Dev Web Server and within the Debug process, but perhaps I am in a new context as another Action is creating the Controller.
1) Any idea why my idea does not work with Session variables?
2) If anybody has a better idea on how to invoke specific Controller Actions then I would appreciate that.
Thanks.
You need to call the Initialize method on your controller before using it. Try something like:
var httpContext = new HttpContextWrapper(HttpContext.Current);
var routeData = RouteTable.Routes.GetRouteData(httpContext);
var controller = new MyApp.Areas.Area1.Controllers.OrderController();
controller.Initialize(new RequestContext(httpContext, routeData));
return controller.Index();
I am new to MVC ASP.NET and needed to call an action from one controller in an action of another controller. There I created object of controller and called my required action as below,
controllerOne co = new controllerOne();
co.requiredFunction();
but one of my senior advised me to not use this approach, which kills the MVC pattern use its given ActionInvoker.InvokeAction() function to call function of other controller and I am using now as below,
public class HomeController : Controller
{
this.ActionInvoker.InvokeAction(new System.Web.Mvc.ControllerContext(
this.ControllerContext.RequestContext, new controllerOne()),
"requiredAction");
}
This works fine, but I don't know if the way I am using ActionInvoker.InvokeAction() is correct. I searched to find any example but I could find any.
So my question is: Am I using it correctly?
To do this many people would create a service that encapsulates this requiredFunction and inject the service through it's interface into both controllers
use this
var ctrl= new MyController();
ctrl.ControllerContext = ControllerContext;
//call action
return ctrl.Action();
If I want to directly access the RouteData (the current action or parameter values for example) from the View, rather than having to pass it in from the controller as part of the ViewData, what class would i use?
this.ViewContext.RouteData
should do the trick.
I have a little question to community. Does ASP.NET MVC allow to execute an action of another controller without RedirectToAction() method and without creation of an instance of this controller?
This is impossible. For an instance method to execute there must be an instance to execute in. Action methods are simply methods like all other methods, so you always need an instance to call the method.
Do you mean you wish to have a View which returns nothing. No view. No nadda?
If so, u can return a EmptyResult ViewResult class...
HTH.
You can call it through the Reflection technic, But It's Not Recommended. Shortly because it's not in the request/response/controller context.
Personally, I prefer to have an internal static method(bla bla){...} and call it where ever i want.
But if you drop the
without creation of an instance of this controller
Clause, Then you can use this methodology. But as it explains, It's Not Recommended Too. the following is summarized:
var controller = new FooController();
controller.ControllerContext = new ControllerContext(this.ControllerContext.RequestContext, controller);
var jsonResult = controller.BlaMethod(someInputParams);
I'm trying to unit test a page in my ASP.NET MVC application that, when posted to, will delete a user's item. I want to restrict this page so that it can only be posted to by the owner of said item. Originally, I wanted to just stick a quick check in the controller that checked if the HttpContext.Current.User.Identity.Name is equal to the owner of the item, but I quickly realized that unit testing this would be difficult.
Should I create an interface that provides a way to access the current logged-in user's name?
You can use this code
Controller CreateControllerAs(string userName) {
var mock = new Mock<ControllerContext>();
mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
var controller = new SomeController();
controller.ControllerContext = mock.Object;
return controller;
}
It uses moq lib
The last line of your question is probably the quickest solution, however, I don't think you need to create the interface, HttpContext.Current.User is already an IPrincipal and HttpContext.Current.User.Identity is already an IIdentity.
If your checking logic uses either of those interfaces, the controller can be mocked to pass an IIdentity that you create instead of the HttpContext.Current.User.Identity
Hope that helps!
I use Thread.CurrentPrincipal.Identity.Name. It's trivial to create a GenericPrincipal for a unit test and attach it.