When a user comes to my site, there may be a template=foo passed in the query string. This value is being verified and stored in the Session.
My file layout looks like this:
- Views/
- Templates/
- test1/
- Home
- Index.cshtml
- test2/
- Home
- List.cshtml
- Home/
- Index.cshtml
Basically, if a user requests Index with template=test1, I want to use Views/Templates/test1/Index.cshtml. If they have template=test2, I want to use Views/Home/Index.cshtml (because /Views/Templates/test2/Home/Index.cshtml doesn't exist). And if they do not pass a template, then it should go directly to Views/Home.
I'm new to MVC and .NET in general, so I'm not sure where to start looking. I'm using MVC3 and Razor for the view engine.
You can do this by creating a custom RazorViewEngine and setting the ViewLocationFormats property. There's a sample here that does it by overriding the WebFormViewEngine, but using the RazorViewEngine should work just as well:
public class CustomViewEngine : WebFormViewEngine
{
public CustomViewEngine()
{
var viewLocations = new[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx",
"~/AnotherPath/Views/{0}.ascx"
// etc
};
this.PartialViewLocationFormats = viewLocations;
this.ViewLocationFormats = viewLocations;
}
}
You could modify Scott Hanselman's Mobile Device demo to fit your needs. Instead of checking the user agent or if it's a mobile device, you could put your logic in to check the query string or your Session vars.
Related
I am trying to create dynamic routes using ASP.Net Core and Razor Pages. Basically, I have two razor pages. One is called Pages/Home.cshtml and another is called Pages/Calendar.cshtml. Each user that logs in has their own username. So let's say I have two users in my database, Sam and Jessica and let's say Sam is logged in and goes to http://www.example.com/Sam, then it should render Pages/Home.cshtml. If Sam is logged in and goes to http://www.example.com/Sam/Calendar, then it should render Pages/Calendar.cshtml. If Jessica is logged in and she goes to http://www.example/com/Jessica, then it should render Pages/Home.cshtml.
So basically, ASP.Net Core should look at the URL and compare the username with what's in the database. If the signed in user's username matches the URL, then it should render their home page. If their username does not match the URL then it should continue down the routing pipeline. I don't need help with the database stuff or anything like that. I only need assistance on how to set up the routing.
If all this sounds confusing, then just think of Facebook. It should work exactly like Facebook. If you go to http://www.facebook.com/<your.user.name>, then it brings up your time line. If you go to http://www.facebook.com/<your.user.name>/friends, then it brings up your friends list.
I am basically trying to duplicate that same behavior that Facebook has in ASP.Net Core and Razor Pages. Can someone please provide a simple example or point me to an example? I feel like the way to do this is to use some custom middleware or a custom route attribute, but I am not sure.
You can do something like this. In the Program.cs/startup.cs modify the AddRazorPages like this.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages(options =>
{
options.Conventions.AddPageRoute("/Index", "{user}");
options.Conventions.AddPageRoute("/Calendar", "{user}/calendar");
});
var app = builder.Build();
Now when you access a URL like https://localhost:7131/sam/calendar you will get the calendar page. You can access the user variable like this - #RouteData.Values["user"]
And on the calendar page, you can do something like this.
public class CalendarModel : PageModel
{
public void OnGet()
{
var user = RouteData.Values["user"];
//Query the calendar information from Database.
//If empty redirect the user to the home page or something.
}
}
You can find more details about this here - Razor Pages route and app conventions in ASP.NET Core
When you create an ASP.Net Core Web App with Individual Accounts it adds an Identity Area along with the regular Pages folder.
Since I don't want to be working between the Pages folder along with the Area folder, I want to create a Home Area that my app's default route "/" will route to.
I was able to accomplish this for the Index page by adding this to Program.cs:
builder.Services.AddRazorPages(options =>
{
options.Conventions.AddAreaPageRoute("Home", "/Index", "");
});
Obviously, this just takes care of the single Index page, but if I wanted to have an About or Privacy page, I would have to add AreaPageRoutes for them as well. I tried a couple different things with AddAreaFolderRouteModelConvention that I am too embarrassed to show here, but was ultimately unable to find out how to make it work.
Is it possible and secondly, is it bad practice, to map the default routing of Pages to a specific Area?
You can use a PageRouteModelConvention to change the attribute route for pages in an area:
public class CustomPageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
foreach (var selector in model.Selectors.ToList())
{
selector.AttributeRouteModel.Template = selector.AttributeRouteModel.Template.Replace("Home/", "");
}
}
}
Generally, my advice regarding areas in Razor Page applications is don't use them. They add additional complexity for no real gain at all. You have already found yourself fighting against the framework as soon as you introduced your own area. QED.
The only place areas serve a real purpose is within Razor class libraries, so you have to live with an area when using the Identity UI. But you don't have to use the Identity UI. You can take code inspiration from it and implement your own version in your existing Pages folder.
Is it possible to create my own custom "view switcher" like MVC4 mobile does?
for example:
If I change my view name to "_Layout.Mobile.cshtml" it'll be automatically render the view if the user-agent is mobile device.
I want to manage couple of sites in one project so I want to allow by configuration(web.config) to call the view with the same way.
for example:
Account.Project1.cshtml (if configured to project 1)
Account.Project2.cshtml (if configured to project 2)
Account.Mobile.cshtml (if called from mobile)
Account.Project1.Mobile.cshtml (if called from mobile and project 1)
Account.cshtml (default)
I tried to google about it but i didn't found any question about this subject.
Thanks.
You can expand the DefaultDisplayMode:
public class MobileDisplay : DefaultDisplayMode
{
public MobileDisplay()
// postfix of the file
: base("mobile")
{
// create an expression if the current postfix is applicatble
ContextCondition = context => context.Request.Browser.IsMobileDevice;
}
}
And you can insert the in the app start:
DisplayModeProvider.Instance.Modes.Insert(0, new MobileDisplay());
This works like the routes and exceptions. First match win so that is why my example insert it to index 0.
The layout is not choosen by this. You can set the layout view per cshtml file or in the _ViewStart.cshtml file.
Of course You can set the mobile layout only in the concrete view or set in the _ViewStart base on logic:
#{
if (Request.Browser.IsMobileDevice)
{
Layout = "Shared/_Layout.mobile.cshtml";
}
else
{
Layout = "Shared/_Layout.cshtml";
}
}
Hello to all developers,
I am trying to find some example of Dynamically generate URL(PURL).
I have seen one software which generate personalised URL from MySQL database .
The only thing is that software is using PHP to generate URL and as a .NET developer I dont know about php.
My question is is there a way that I can fetch data from data base and using perticular field i can generate url which is not actually store in my web space..
eeg.
-----database-----
firstname | lastname ....
===========================
xyz abc
pqwert qweoiuy
alfa beta
the URL should be like
http://something.com/somepersonal/xyz_abc.aspx
http://something.com/somepersonal/pqwert_qweoiuy.aspx
http://something.com/somepersonal/alfa_beta.aspx
It is something like personalised page for users or clients.
I have template to use as back page but dont know how to plug and dynamically generate URL..
You're thinking of this a little backward. Generally, one wouldn't do this by generating it directly from the database. You would generally do this by routing the url batch /somepersonal/ to some personalpage control, which would then consider everything after it, like xyz_abc to be an argument. Personalpage would then use that argument to customize its display, be it from the database or wherever.
So to clarify, your URL would look something like:
http://something.com/personal/vish_soni
http://something.com/personal/colonel_gentleman
http://something.com/personal/general_specific
But all of these are being routed to Personalpage, which then uses vish_soni, colonel_gentleman, and general_specific as arguments to query the database or do whatever else it needs to do.
Microsoft has an overview of this pattern and routing in general here.
You can create a controller class and call an action method. For your case, you just need to send parameter and then lookup customer info to prepare the content.
public class HomeController : Controller
{
public ActionResult Me(string id)
{
ViewBag.Message = "Welcome to ASP.NET MVC! "+id;
var contentobj = repository.GetUSerContent(id);
return View("Index",contentobj);
}
}
I have the basic Master / Detail Views working great with the default ASP.NET MVC Route; however I would like to build some URLs like this:
/Class/Details/5 -- General Detail view [Working]
What I'm not sure about (and I'm not tied to this URL format, just something roughly equalivent.)
/Class/5/Details/Logs -- Detail View with Logs
/Class/5/Details/Status -- Detail View with current Status
Another way to put this, is like this:
/{controller}/{id}/{controllerSpecificMaster}/{action}/
What I'm trying to avoid, is cluttering up my Views\Class directory with a bunch of Views, which are all basically derivatives of the Details view.
I'm on ASP.NET MVC 1 and .NET 3.5 SP1.
The first thing you need to get down are your routes. You may have already done this, but in case you haven't, here's a route entry that will handle your custom route needs:
routes.MapRoute("Master_Detail",
"{controller}/{id}/{controllerSpecificMaster}/{action}",
new { controller = "Class",
action = "Index",
id = UrlParameter.Optional,
controllerSpecificMaster = "Details"
});
Then, in your action methods where you want to use the route-specified master page, just include the route key in your method arguments, and then pass it to the view:
public ActionResult Logs(int id, string controllerSpecificMaster)
{
//do something
//return view with master name as argument
return View("Logs", controllerSpecificMaster);
}
If you have to do this a lot, I would suggest creating a custom view engine and override the FindView() method.