ASP.NET MVC: Generate URLs without specifying the actionName - c#

This is how I generate a URL in ASP.NET MVC currently:
Url.Action("Index", new { page = 2 })
In previous frameworks I have used, there were special url functions which created a url based on the current url, only modifying the parts you wanted to change. This is in Pylons:
{{ url.current(page=2) }}
This would come in handy with partial views, where the partial view may be showing a list of items but not necessarily know which controller they belong to.
Two questions - why is such an obviously useful feature missing from ASP.NET MVC, and is there some common alternative way of doing what I mentioned with partial views? Maybe I'm approaching partial views completely wrong?

why is such an obviously useful feature missing from ASP.NET MVC
What makes you think that such feature is missing:
string url = Url.Action(null, new { page = 2 });
or:
string url = Url.RouteUrl(new { page = 2 });

Related

Page route prevents OnGet() receiving query argument

I'm porting a WebForms application to Razor Pages, and I'm using the following route to prevent breaking one of my URLs.
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/Resources/CharClass", "/Resources/CharClass.aspx");
});
But using the code below, when I use the URL /Resources/CharClass.aspx?page=500, page is always null.
cshtml
#page "{page:int?}"
cshtml.cs
public void OnGet(int? page)
{
//
}
The argument seems to work okay for pages that aren't routed this way. How can I have both?
I suspect that the problem you have is with the name of the parameter - page. This seems to conflict with the Page property of the PageModel class, and nothing is bound during model binding. You can however access the query string value using traditional methods:
var page = Request.Query["page"];
EDIT: Just seen that this is partly covered in a reply to your other question on the issue: Razor page link ignores route argument
Try:
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/Resources/CharClass", "/Resources/CharClass.aspx/{page?}");
});

index.html couldn't be found after migrating to MVC 4 [duplicate]

This question already has answers here:
How to serve html file from another directory as ActionResult
(6 answers)
Closed 5 years ago.
We have a .NET 4.0, MVC 2 project, where the HomeController looks like this:
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View("~/client/index.html");
}
}
All is fine.
But, when we start linking to .NET 4.5 and MVC 4, the runtime can't seem to find this index.html! We get this error:
The view '~/client/index.html' or its master was not found or no view
engine supports the searched locations. The following locations were
searched: ~/client/index.html
How could this be! What might we be missing here.
I've never seen MVC using straight html pages. This is a more typical setup:
Controller
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View("Index");
}
}
The view would be /views/Home/Index.cshtml. By default MVC wants views to be in the views folder in a folder corresponding to the controller name.
If you want to have the layout broken into a separate file it would typically be in /views/Shared/.
If your HTML page is self-contained you should be able to move it and rename it to index.cshtml and add the following somewhere on the page.
#{
Layout = null;
}
Take care when locating your html page. Placing it inside a view folder where, by the MVC rules, a controller would be expected to do the handling, causes errors in my testing. Here's one way to make it work, though this isn't really coding to MVC pattern:
You can then reference the page:
Notice I've stepped outside the controller/view structure (not recommended for MVC)
To make it fail, which I'm assuming is similar to what is happening for you:
(notice the html is placed in a view where we'd expect a matching controller method to serve it to a caller)...
But...
So if you insist on going this approach perhaps you can set up a content folder outside your MVC controller/view structure and place your html there. But, again, not to beat the subject to death, you could easily convert this to cshtml and serve it up via a simple method in a controller. Just my two cents' worth..

How to create new URL views in asp .net MVC at run time(as like Stackoverflow)?

In my new project i need to create new static url Views with user content at run time in asp.net MVC.
For that i have taken Stackoverflow as an example.
In SO when we ask the question we will type our question here and finally we go for "Post your question" button.
Once we post the question one new static URL will be generated with our contents(i'm not sure they may handle it through some url routing mechanism).
And my question is:
How should i create new static URL views(with contents) in runtime using asp .net MVC?
Note: I considered about UrlHelper.GenerateUrl but im not sure is this correct approach and i'm little bit concerned if we keep on add views into our solution the size of solution will be so much bigger at some point of time.Is there any better approach to over come this issue?
Basic routing and querying content based on ID:
routes.MapRoute(
"questionsFull",
url: "questions/{questionId}/{questionTitleForSeo}",
defaults: new { controller = "Questions", action = "Full"});
And in your controller read article by questionId
class QuestionController
{....
ActonResult(string questionId) { return ArticleById(questionId);}
To create urls in the Razor view (assuming you have question variable - i.e. if you pass list of "Question" objects as model):
<a href="#Url.Action("Full", "Question", new {question.Id})>
#question.Title</a>

ASP.NET MVC map single controller to root of website

I am working on an ASP.NET MVC 5 website that has a public "marketing" website that contains somewhat static pages with information about the company, legal, social, contact us, etc. that a non-logged in user can access. Then, once logged in, there is a back end of the website that registered users have access to features.
Originally I had all the public "marketing" pages going to http://www.mywebsite.com/Marketing/About, http://www.mywebsite.com/Marketing/Social, etc.
However, the business wants all the "marketing" pages, to be accessible a single directory down from the root website, so the links above would be accessible with:
http://www.mywebsite.com/About, http://www.mywebsite.com/Social, etc.
I know I can use the below approach to get it to work by registering individual routes for each "marketing" page like so:
routes.MapRoute(
"ShortAbout",
"About",
new { controller = "Marketing", action = "About" }
);
routes.MapRoute(
"ShortSocial",
"Social",
new { controller = "Marketing", action = "Social" }
);
However, since there are about 15 "marketing" pages, this seems inefficient and it seems like there must be a better way to do this.
I also tried a generic routing approach outlined here: http://www.wduffy.co.uk/blog/aspnet-mvc-root-urls-with-generic-routing/
but the problem with that approach was I had a "marketing" page, with the same name as a controller and it ended up forwarding the user to the marketing subdirectory. For example, I had a Controller called "MachineController", and in the "MarketingController" I had an action/page called "Machine", so it was forwarding the user to /Marketing/Machine using the approach in the above link.
Any other ideas? Thanks in advance.
I had exactly this problem. A much simpler but more hardcoded solution is
routes.MapRoute("MarketingPages", "{action}",
new { controller = "Marketing" },
new { action = #"About|Social" });
The last anonymous object constrains the route to match routes where action matches the supplied regular expression, which is simply a list of the urls you want to have marketing pages. Any other url like '/something' falls through to the routes below.

CSHTML files not loading outside of Views

I have a C# MVC Razor site. Typically, Controllers load views from the Views folder. However, I have a special circumstance where I need to render a view outside of the Views folder. How do I do that?
Controller will load /Views/Random/Index.cshtml
Can't load /Random/Index.cshtml
/Random/test.aspx loads with no issues, but can't change cshtml files to aspx files, they need to be built regularly.
I have tried return Redirect("/Random/Index.cshtml") in the Controller, and currently have no controller at all.
The weird thing is it works on my Production environment, but not in localhost. In localhost I get:
The type of page you have requested is not served because it has been explicitly forbidden. The extension '.cshtml' may be incorrect. Please review the URL below and make sure that it is spelled correctly.
Requested URL: /Random/Index.cshtml
You can definitely do this. For doing this you need to create one new custom view engine like
public class MyViewEngine : RazorViewEngine
{
private static string[] AdditionalViewLocations = new[]{
"~/Random/{0}.cshtml"
};
public MyViewEngine()
{
base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(AdditionalViewLocations).ToArray();
base.ViewLocationFormats = base.ViewLocationFormats.Union(AdditionalViewLocations).ToArray();
base.MasterLocationFormats = base.MasterLocationFormats.Union(AdditionalViewLocations).ToArray();
}
}
Then in you global.asax's Application_Start method register this view engine like this-
ViewEngines.Engines.Add(new MyViewEngine ());
If you want your viewengine to take precedence then insert this at 0th position. like this -
ViewEngines.Engines.Insert(0, new MyViewEngine());
return View("~/AnotherFolder/Index.cshtml")` should work for you.
Do not forget to indicate the Layout in your index view:
#{
Layout="~/Views/Shared/Layout.cshtml";
}

Categories