I have the following code
public class BooksController : Controller
{
[Route("/Books/{id?}")]
public IActionResult Index(string id)
{
return View(id);
}
}
My problem is that when I try to enter the parameter it is (as it seems) considered as controller's action so I keep getting this exception.
I need somebody to explain what am I doing wrong.
If you want to pass some parameter to a view as a string you can make this like below:
public class BooksController : Controller
{
[Route("/Books/{id?}")]
public IActionResult Index(string id)
{
if (string.IsNullOrEmpty(id))
id = "default_value";
return View((object)id);
}
}
If the string type is passing to the View() call without casting to object it will be interpreted as a view name.
And the view model data should be declared as
#model string;
<h2>#Model</h2>
Try changing the route as given below -
[Route("Books", Name = "id")]
Related
I am trying to handle a returnUrl string after login request such that:
if (returnUrl is pointing to a ViewResult)
proceed to the requested destination
else
Redirect to home
How do I determine if the url is pointing to a controller method with a return type of ViewResult?
How do I determine if the url is pointing to a controller method with a return type of ViewResult?
First, this is not a good idea. If a result of a method is ActionResult you can not ever 100% know if the result is a ViewResult, because someone could change it.
If you are really determined to do this, then every return value on every controller would have to be ViewResult. Then what you can do is create a custom AuthorizationAttribute which could then determine if the user is logged in, if the ReturnUrl is populated (or some other flag) and then using reflection (which is not great for performance, but it's only on sign-in so thats mostly ok) to determine the method's return type.
I don't see why "every return value on every controller would have to be ViewResult."
Because if you don't do this, you cannot guarantee a method with a return type of ActionResult is a ViewResult.
DotNetFiddle Example
using System;
public class Program
{
public static void Main()
{
var result = typeof(TestController).GetMethod("MyMethod").ReturnType;
Console.WriteLine("TestController:MyMethod returns {0}", result.Name);
}
public class TestController
{
public ActionResult MyMethod()
{
return new ViewResult();
}
}
// mocking System.Web.Mvc
public abstract class ActionResult { }
public class ViewResult : ActionResult { }
public class JsonResult : ActionResult { }
}
Result
TestController:MyMethod returns ActionResult
Someone changes new ViewResult() to Json(myModel) you can't detect the change through reflection.
I have the following controllers
public class StoreController : Controller
{
public ActionResult Index()
{
var model = new SomeViewModel();
return View(model);
}
}
and
public class SofiaStoreController : StoreController
{
public ActionResult GetIndex(string city)
{
return base.Index();
}
}
When invoking the base Index method from the derived class I get this error:
The view 'getindex' or its master was not found or no view engine
supports the searched locations. The following locations were
searched:
Seems the GetIndex() method looks for a view in the derived controller's view folder by default even though no View() method is called but since there isn't such the error occurs.
Any idea why the method implicitly looks for a view and how to overcome the error ?
EDIT: After spending some time research the problem I came across these two posts: http://howtoprogram.eu/question/asp-net-c-asp-net-mvc-inherited-controller-using-base-view,2445 and http://www.davidwhitney.co.uk/Blog/2010/01/19/asp-net-mvc-view-engine-that-supports-view-path-inheritance/ Seems that controller inheritance is not that popular or straightforward decision. The solutions to my problem could be :
1. Not to use controller inheritance
2. Creating a custom view engine as shown in the second link (advanced)
3. As other people mentioned bellow - using full path to the view or RedirectToAction also could work
It does look for a view based on the Action method name you originally called. You can always override this behavior if you use the overloaded View() method that accepts the view name/path:
public class StoreController : Controller
{
public ActionResult Index(string viewName = "Index")
{
var model = new SomeViewModel();
return View(viewName, model);
}
}
public class SofiaStoreController : StoreController
{
public ActionResult GetIndex(string city)
{
return base.Index();
}
}
I'm trying to get the parameters of specific attribute routed URL on ActionFilterAttribute. For instance I have an action like below:
[Route("/v1/test/{userId}/{udid}")]
public object GetNewObject(int userId, string udid)
And in action filter attribute the absolute url is coming something like "http://test.example.com/v1/test/1/123-asda-231-asd". However I want to parse these parameters as userId=1 and udid=... within a collection.
Is it possible?
Anyway I found the answer,
Within RouteData of ControllerContext we may able to retrieve the specified value.
actionContext.ControllerContext.RouteData.Values["udid"]
[Route("...")] is possible only in MVC 5.
I think you want to do something like this
[RoutePrefix("api/users")]
public class UsersController : ApiController
{
// GET api/users
[Route("")]
public IEnumerable<User> Get() { ... }
// GET api/user/5
[Route("{id:int}")]
public Book Get(int id) { ... }
// POST api/users
[Route("")]
public HttpResponseMessage Post(User book) { ... }
}
where each User contains your properties
public class User
{
int UserId{get;set;}
string Udid{get; set;}
}
Is it somehow possible to set alternate names for querystring parameters in ASP.NET MVC?
I have this simple controller Index action:
public ActionResult Index(color = "")
{
...
}
Calling http://mysite.com/mypage/?color=yellow works quite nicely, the color parameter automatically picks up its value "yellow" from the querystring.
But now I would like to have a localized variant of the same page, with “pretty” localized parameters, but still working with the same controller method. Example: http://mysite.com/mypage/?farve=gul. Here I would like “gul” to be passed in as the color parameter to the default Index() ation method.
How do I set mappings for alternate names for querystring parameters?
How do I set mappings for alternate names for querystring parameters?
You could write a custom model binder.
So as in every ASP.NET MVC application you start by writing a view model:
public class MyViewModel
{
public string Color { get; set; }
}
and then a model binder for this model:
public class MyViewModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var query = controllerContext.HttpContext.Request.QueryString;
var value = query["color"] ?? query["gul"] ?? query["couleur"];
return new MyViewModel
{
Color = value,
};
}
}
which will be registered at your Application_Start:
ModelBinders.Binders.Add(typeof(MyViewModel), new MyViewModelBinder());
and now your controller action may take the view model as parameter:
public ActionResult Index(MyViewModel model)
{
...
}
Of course you could make the model binder more flexible by using some custom attribute on the property:
public class MyViewModel
{
[PossibleQueries("color", "gul", "couleur")]
public string Color { get; set; }
}
and in the model binder read those values and try reading them from the query string until you find one that is not null.
How about a second controller with a localized/pretty name where the actions and parameters have localized names and call the actions from the default/english controller? With this method you have all parts of the url localized.
Controller mypage
{
ActionResult Index(string color)
{
// normal code
}
}
Controller meineseite
{
ActionResult Index(string farbe)
{
return mypage.Index(farbe);
}
}
i have done as Vdex suggested here:
https://stackoverflow.com/a/5801502/973485
And used the RenderPartialToString method he found. And it works perfectly like this:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Test()
{
string t = ViewToString.RenderPartialToString("Index", null, ControllerContext);
return Content(t);
}
}
But if i want to render the Home > Index from another Controller, i get:
Value cannot be null.
Parameter name: controllerContext
Like this:
public class FooController : Controller
{
public ActionResult Index()
{
string t = ViewToString.RenderPartialToString("Index", null, new HomeController().ControllerContext);
return Content(t);
}
}
Is there any way to pass a View from another Controller to a string? I have tried many different methods, and it all of them fails at the ControllerContext. Many thanks!
Update: Why i need to do this:
Imagine i have a website full of widgets, the amount of widgets on each page is dynamic, so i cannot hardcode them in my cshtml file. But in that file there are different areas defined where the widgets gets printet out. To print out these widget i have a list of IWidgetController wich contains alle the different Widgets available, and the interface sais that they need to containe a ActionResult for edit, new and view. example of widgets: CalenderController, NewsController, GalleryController and so on... So in those areas i need to print out the content of each of those Controllers. Now i could also load the URLHTML but i figured doing it from the inside would be faster... right?
Try this:
string t = ViewToString.RenderPartialToString("Index", null, this.ControllerContext);
Anyway, why do you need to convert to a string?