I had this public function in ApplicationController
public function indexAction($bar) {
echo $bar;
return new ViewModel();
}
How I can pass this argument? I've tried http://localhost/zf2/public/application/index/index?bar=foo
but this not works
Grab it from params controller plugin.
public function indexAction()
{
$bar = $this->params()->fromQuery('bar');
return new ViewModel();
}
Related
My existing MVC code contains an action routine something like this:
[HttpPost]
public ActionResult Register1(SomeViewModel model)
{
return RedirectToAction("Register", new { p = model.PageNumber - 1 });
}
I want to move this code to a library routine:
public static ActionResult ProcessPost(Controller controller, string action,
int pageNumber)
{
// Redirect to the specified action on the specified controller
return new RedirectToRouteResult( <something here> );
}
and call it from the action routine like this:
return ProcessPost(this, "register", model.PageNumber);
Can some kind person give me the <something here> code that yields an ActionResult that redirects to the specified action (specified by the string argument) on the specified Controller (specified by the Controller argument?
Taking a look at the documentation on RedirectToRouteResult seems pretty straight forward:
var routeValues = new RouteValueDictionary();
routeValues.Add("Action", action);
routeValues.Add("Controller", controller.GetType().Name);
routeValues.Add("PageNumber", pageNumber);
var result = new (RedirectToRouteResult(routeValues);
After some experimentation, this appears to be a simple solution:
return new RedirectResult(controller.Url.RouteUrl(
new { action = action, p = pageNumber }
));
Apparently, the Url method on a specific Controller instance is smart enough to use that instance to get the controller name part of the full URL.
This is my code:
public class StoreController:Controller
{
public ActionResult Index()
{
var page=new PageHelper<Store>();
return page.PageView(this);
}
}
public class PageHelper<T>
{
public List<T>DataSouce {get;set;}
public ActionResult PageView(Controller controller)
{
var action = controller.RouteData.Values["action"].ToString();
if (controller.Request.IsAjaxRequest())
//my question is it can not call the PartialView or controller.View
return controller.PartialView(action);
return controller.View(DataSource);
}
}
I can not call the PartialView or controller.View in PageView function.
how I can do it?
now this code:"controller.PartialView(action);" in PageView function will be compiled
error. why can not call the View() or PartialView()?
View and PartialView are protected internal methods.
The type or member can be accessed by any code in the assembly in
which it is declared, or from within a derived class in another
assembly.
you should make your class PagerHelper inherit from Controller.
After that you can call inside your PageView method
public ActionResult PageView(Controller controller)
{
ViewBag.DataSource = DataSource;
ViewBag.PageHtml = PageHtml;
ViewBag.AjaxPageHtml = AjaxPageHtml;
if (controller.Request.IsAjaxRequest())
return PartialView(AjaxTag);
var action = controller.RouteData.Values["action"].ToString();
return View(action);
}
I have tested your project and now it works.
I have following line of code in my Controller/Action
var defaultRoute = Url.RouteUrl("Default", new { action = "MyAction", controller = "MyController", id = 1 });
I am writing a Unit Test and Need to Mock this line to make it return some URL. I am not getting how i can do so. Can anyone help me to write a Test for this Line.
THanks
I think I found a thread related to your problem: How do I MOQ the System.IO.FileInfo class... or any other class without an interface?
The problem is that you can't mock classes that don't implement an interface or have the respective method/property set to virtual.
You could always create a wrapper class for the untestable one, and then mock that:
public interface IUrlRouterWrapper
{
// Put any methods you want to mock here...
void RouteUrl(string routeName, RouteValueDictionary routeValues);
}
public class UrlRouterWrapper : IUrlRouterWrapper
{
// ... and implement them here, calling through to the real, non-testable class.
public void RouteUrl(string routeName, RouteValueDictionary routeValues)
{
Url.RouteUrl(routeName, routeValues);
}
}
And then in your code that uses RouteUrl:
public class SomeOtherClass
{
private readonly IUrlRouterWrapper _urlRouterWrapper;
public SomeOtherClass(IUrlRouterWrapper urlRouterWrapper)
{
_urlRouterWrapper = urlRouterWrapper;
}
public void DoThings()
{
// ...
_urlRouterWrapper.WrapUrl("Default", new { action = "MyAction", controller = "MyController", id = 1 });
// ...
}
}
Now you have an easily-mockable interface, IUrlRouterWrapper, that you can test to your heart's content.
There is a simple controller that a querystring is read in constructor of it.
public class ProductController : Controller
{
parivate string productName;
public ProductController()
{
productName = Request.QueryString["productname"];
}
public ActionResult Index()
{
ViewData["Message"] = productName;
return View();
}
}
Also I have a function in unit test that create an instance of this Controller and I fill the querystring by a Mock object like below.
[TestClass]
public class ProductControllerTest
{
[TestMethod]
public void test()
{
// Arrange
var querystring = new System.Collections.Specialized.NameValueCollection { { "productname", "sampleproduct"} };
var mock = new Mock<ControllerContext>();
mock.SetupGet(p => p.HttpContext.Request.QueryString).Returns(querystring);
var controller = new ProductController();
controller.ControllerContext = mock.Object;
// Act
var result = controller.Index() as ViewResult;
// Assert
Assert.AreEqual("Index", result.ViewName);
}
}
Unfortunately Request.QueryString["productname"] is null in constructor of ProductController when I run test unit.
Is ther any way to fill a querystrin by a mocking and get it in constructor of a control?
There is a simple controller that a querystring is read in constructor of it.
You shouldn't be doing this and such controller shouldn't exist. The controller context is not yet initialized in the constructor and it will fail not only for the unit test but in real.
You should use the Initialize method where you have access to the request context.
Using MVCContrib you can easily do RedirectToAction calls such as
this.RedirectToAction( c => c.List() );
where List is an action result in said controller. Is there a way to do the same but using the "View" method instead? I.E
this.View( c => c.List(), viewModel );
Here's a trivial but complete example:
[HttpGet]
public ActionResult Profile()
{
return View( new ProfileViewModel() )
}
[HttpPost]
public ActionResult Profile( ProfilePostModel postModel )
{
if( !ModelState.IsValid )
return this.View( c => c.Profile(), postModel.MapToViewModel() );
_service.Save(postModel.MapToDtoObject() );
return this.RedirectToAction( c => c.SomeOtherAction() );
}
I've been searching around and haven't found anything relevant.. Thanks!
I don't know if such method exists in MVCContrib but it would be trivial to write one:
public static class ControllerExtensions
{
public static ViewResult View<T>(
this T controller,
Expression<Func<T, ActionResult>> expression,
object model
) where T : Controller
{
var mce = expression.Body as MethodCallExpression;
if (mce == null)
{
throw new NotSupportedException();
}
var result = new ViewResult();
result.ViewName = mce.Method.Name;
result.ViewData.Model = model;
return result;
}
}
As there is no code that represents the view itself, I don't think this can be made out-of-the-box.
You can achieve something similar if you create conventions on how you choose which views are rendered.
You can get some ideas from this post Jimmy Bogard's blog.