MVC5 Dynamic route on the root - asp.net-mvc-5

I want the following to urls to be mapped dinamically to the HomeController => Index with the segment variable...
www.site.com/one
www.site.com/two
public HomeController
{
[Route("{segment:string}")]//this wont work... 404
public ActionResult Index(string segment) //one or two
{
return View();
}
}

I think I managed to do it like this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
// other routes
}
}
[RoutePrefix("")]
public class HomeController : Controller
{
[Route("{segment}")]
public ActionResult test(string segment)
{
return View();
}
}
and accessed the following urls:
http://localhost/TestWebApplication/segment1 -> goes to test action -> put segment = "segment1"
So, shortly put: make sure that attribute routing is enabled and skip the string constraint (I receive an error that is not recognized).

Related

Call a method in a CORE Razor Page from a ViewModel

My Razor Page
public class IndexModel : BaseModel {
public void OnGet() {
BaseModelMethod();
}
public void LocalMethod() {}
}
calls a method in the base ViewModel
public class BaseModel : PageModel {
public void BaseModelMethod() {
// Do stuff
}
}
Is there a way to call back to the instance of LocalMethod in the calling Razor Page?
You have to define the function as a virtual function. Your BaseModel has to have the following form:
public class BaseModel : PageModel
{
public void BaseModelMethod()
{
LocalMethod();
}
public virtual void LocalMethod()
{
}
}
As you can see I creted the virtual function so that we will know what we kind of method we will call.
Now we can define our own version of LocalMethod like this:
public class IndexModel : BaseModel
{
public void OnGet()
{
BaseModelMethod();
}
public override void LocalMethod()
{
base.LocalMethod();
}
}

MVC 5 View from base controller (controller inheritance)

does anyone know how tell the child controller to load base (parent) controller view instead of looking for it in it's own folder?
public class BaseController : Controller
{
public virtual ActionResult Test()
{
return View("Test");
}
}
public class ChildController:BaseController
{
public override ActionResult Test()
{
return base.Test();
}
And the Error is The view 'Test' was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Child/Test.cshtml.....
So the solution that I found yeat is to make parent action looks like this
public class BaseController : Controller
{
public virtual ActionResult Test()
{
return View("~Views/Base/Test.cshtml");
}
}
Is there any better solution ?
private const string ViewPath = "~/Views/{0}/{1}.cshtml";
private ViewResult GetView(string action, object model = null)
{
var controllerName = ControllerContext.RouteData.Values["controller"].ToString();
var path = string.Format(ViewPath, controllerName, action);
return
new ViewResult
{
ViewName = path
};
}

AmbiguousMatchException exception in ServiceStack?

PFB my code.
namespace ManualCSharpe
{
public class MyServices : Service
{
[Route("/L/hello/")] //RequestDTO one
public class HelloL
{
public string Name { get; set; }
}
[Route("/H/hello/")] //RequestDTO two
public class HelloH
{
public string Name1 { get; set; }
}
public class HelloResponse //ResponseDTO
{
public string Result { get; set; }
}
public class HelloServiceL : Service //Service One
{
public object Get(HelloL request)
{
return new HelloResponse { Result = "Low" };
}
}
public class HelloServiceH : Service //Service
{
public object Get(HelloH request)
{
return new HelloResponse { Result = "High" };
}
}
//Define the Web Services AppHost
public class AppHost : AppSelfHostBase
{
public AppHost()
: base("HttpListener Self-Host",new Assembly[] {typeof(HelloServiceL).Assembly, typeof(HelloServiceH).Assembly}) { }
public override void Configure(Funq.Container container) { }
}
//Run it!
static void Main(string[] args)
{
var listeningOn = args.Length == 0 ? "http://*:133/" : args[0];
var appHost = new AppHost()
.Init()
.Start(listeningOn);
Console.WriteLine("AppHost Created at {0}, listening on {1}",
DateTime.Now, listeningOn);
Console.ReadKey();
}
}
}
When I am tring to added two service then it is show below exception.
An unhandled exception of type 'System.Reflection.AmbiguousMatchException' occurred in ServiceStack.dll
Additional information: Could not register Request 'ManualCSharpe.MyServices+HelloL' with service 'ManualCSharpe.MyServices+HelloServiceL' as it has already been assigned to another service.
Each Request DTO can only be handled by 1 service.
I have below douts.
Here I have created two different DTO for Two Service. Why it is showing error like Each Request DTO can only be handled by 1 service. In simple word, Two route mapped with two DTO with two Service.
Can I create one route for multiple RequestDTO with multiple service? In Simple word, One Route/L/hello/ can be mapped with two DTO HelloL and HelloH.
You can't have Service class implementations nested inside another outer MyServices class:
public class MyServices : Service
{
[Route("/L/hello/")] //RequestDTO one
public class HelloL
{
public string Name { get; set; }
}
[Route("/H/hello/")] //RequestDTO two
public class HelloH
{
public string Name1 { get; set; }
}
public class HelloResponse //ResponseDTO
{
public string Result { get; set; }
}
public class HelloServiceL : Service //Service One
{
public object Get(HelloL request)
{
return new HelloResponse { Result = "Low" };
}
}
public class HelloServiceH : Service //Service
{
public object Get(HelloH request)
{
return new HelloResponse { Result = "High" };
}
}
}
Remove the outer MyServices class completely and just have the DTO's and Service classes directly under a C# namespace.
Also routes shouldn't end with a / suffix, so I'd change:
[Route("/L/hello/")]
to:
[Route("/L/hello")]
#mythz answer is correct for OP but I came here looking for an answer for a different situation which the cause was not particularly obvious - you will get this exception if you attempt to register the same assembly twice, for example, if you move a service implementation into the same assembly and were pulling it in like so:
public AppHost() : base("App", typeof(AdminService).GetAssembly(), typeof(InboundService).GetAssembly(),typeof(ProductService).GetAssembly())
For those of you who come here from a google search, a AmbiguousMatchException exception in ServiceStack can sometimes be triggered within ServiceStack but handled internally.
You can change your exception setting so it doesn't break on this exception.
I had changed my exception setting to break on all exceptions and this had me stuck for a while.

mvc5 attribute based routing not working

I am using visual studio 2013 and created a default mvc project.In home controller I have modified the below
[RoutePrefix("home")]
[Route("{action=index}")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
//[Route("Home/About")]
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
In RouteConfig.cs I have done the following modification
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
//routes.MapRoute(
// name: "Default",
// url: "{controller}/{action}/{id}",
// defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
//);
}
}
This is not working.But when I go for convention based routing it is working. Plz help me.
to make a web api create a WebApiConfig.cs :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
}
}
}
in your global.asax :
GlobalConfiguration.Configure(WebApiConfig.Register);
and then you can define controller :
[RoutePrefix("home")]
public class HomeController : ApiController
{
[Route("action")]
public string myaction()
{
return "hello world";
}
}
this way the route /home/action will send back the defined string
now the big difference between WebApi and MVC is that you dont use your server side to Template and provide views, it is mainly used for REST actions: GET PUT POST DELETE
I don't know what you want to achieve but I hope this will be usefull
Edit:
I was thinking maybe you forgot to register your MVC routes in global.asax there should be a similar call to make like:
GlobalConfiguration.Configure(RegisterRoutes.routes);
something like that
and in your code try to change :
[RoutePrefix("Home")]
public class HomeController : Controller
{
[Route("Index")]
public ActionResult Index()
{
return View();
}
[Route("About")]
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
and routes should be /Home/Index and /Home/About

Getting User Identity on my base Controller constructor

I have a base Controller on my ASP.NET MVC4 website that have a Constructor simple as this:
public class BaseController : Controller
{
protected MyClass Foo { get; set; }
public BaseController()
{
if (User.Identity.IsAuthenticated))
{
Foo = new MyClass();
}
}
}
However I cannot access User here. It's null. But on my inherited Controllers it's fine.
Thanks
Controller instantiation will occur before authorisation takes place. Even if your MVC application calls RenderAction() several times and you end up creating say, five different controllers, those five controllers will be created before any OnAuthorization takes place.
The best approach to deal with these situations is to use Action Filters. The Authorize Attribute is fired early and may well be suited to your situation.
First, let's create an AuthorizationFilter.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyClassAuthorizationAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Controller.ViewData["MyClassInstance"] = new MyClass();
}
}
}
Now let's update our Controller
[MyClassAuthorization]
public class BaseController : Controller
{
protected MyClass Foo
{
get { return (MyClass)ViewData["MyClassInstance"]; }
}
}
In this case I would override Controller Initialize method:
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
// User.Identity is accessible here
}

Resources