AngularJS $routeProvider and relative URLs in ASP.NET MVC - asp.net-mvc

I'm totally new to AngularJS. Just wanted to try out relative URLs with $routeProvider.
Here is the scenario:
I have a "Edit" page, the ASP.NET MVC link to the page would be:
http://localhost/Workflow/Edit
So the ASP.NET MVC Controller is "WorkflowController" and the action is "Edit". For the Partials I have Controller actions that each return a Partial View like this:
public ActionResult WorkflowTransition()
{
return PartialView("WorkflowTransition");
}
public ActionResult WorkflowTransitionApprovers()
{
return PartialView("WorkflowTransitionApprovers");
}
Following is the AngularJS module configuration - note: a PartialView (as mentioned above) is called for each of the routes (this could be incorrect):
$routeProvider.when('Workflow/WorkflowTransition', {
templateUrl: '/Workflow/WorkflowTransition',
controller: 'transitionCtrl',
});
$routeProvider.when('Workflow/WorkflowTransitionApprovers', {
templateUrl: '/Workflow/WorkflowTransitionApprovers',
controller: 'approversCtrl'
$routeProvider.otherwise({
redirectTo: '/'
});
Note: I have not specified either of the following:
$locationProvider.html5Mode(false);
OR
$locationProvider.html5Mode(false).hashPrefix('!');
The href links are specified like this:
{{workflow.Identifier}}
This generates links of this form:
http://localhost/Workflow/Edit#/Workflow/WorkflowTransition
This is obviously wrong (and clicking the link doesn't do anything probably because the browser tried to navigate to the hash), so I have tried the leading '/', but no luck there too:
{{workflow.Identifier}}
If I navigate the partial directly i.e. http://localhost/Workflow/WorkflowTransition, the browser renders the html as-is (along with the angularjs curly braces {{}}).
My question is: How does AngularJS treat the '#' or '#!' when it comes to determining relative URLs? For e.g. does this route (assuming I knock off the /Edit part from the URL in the anchor tag):
$routeProvider.when('Workflow/WorkflowTransition', match the URL:
http://localhost/Workflow/#WorkflowTransition ?
Does it remove the '#' from the URL and then check it against the URL pattern in $routeProvider.when() ?
Can someone please suggest correct routes for the relative URLs?

From my observation, the hash has to be removed when matching routes. I have a link like
<a href="#Objects">
resulting in the URL
http://localhost:55033/#/Objects
My route Setup is
$routeProvider.when("/Objects", {
templateUrl: "objects.html",
controller: ObjectCtrl
});
And this works as expected, pulling in the correct partial. Note that I am not Rendering partials through ASP.NET MVC Controllers in this case. Instead I have objects.html lying around as plain html file and I am using the hash in the href so the ASP.NET MVC Routing does not kick in.

Routeprovide should be setup like below.
$routeProvider.when('/Workflow/WorkflowTransition', {
templateUrl: "WorkflowTransition.html",
controller: WorkflowTransitionCtrl
});
and URL should be enter in below formate.
http://localhost/#/Workflow/WorkflowTransition ?

Related

Routing in MVC, "Specify a root relative path with a leading '/'"

I had a razor page called Submit that was giving me a Value cannot be null. Parameter name : viewData error so I removed the #page at the top of my code as this post directed. My issue now is that when I load the page I the following error:
InvalidOperationException: The relative page path 'Index' can only be used while executing a Razor Page. Specify a root relative path with a leading '/' to generate a URL outside of a Razor Page. If you are using LinkGenerator then you must provide the current HttpContext to use relative pages.>
I want my page to have a URL of https://localhost:44369/Submit How would I do this? Here is my routing in my Startup.cs file:
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
The reason you are getting the error is because of incorrect syntax. In one of your Razor Views, you probably have an anchor tag that might look like:
<a asp-page="Index">Index</a>
That syntax (without the forward slash /)is meant for a Razor Page. In the Razor View, prefix the Page name with a forward slash:
<a asp-page="/Index">Index</a>
If everything else is correct you should be able to browse https://localhost:44369/Submit and it should show the whatever is written in your Submit page
You might use Razor Pages asp-action in a MVC project.
For MVC
1> Using tag asp-action but not asp-page to redirect.
<a asp-action="Submit" class="btn btn-success form-control">Submit</a>
2> use Route Attribute to route to the specified view .
Controller.cs
public class HomeController : Controller
{
[Route("/Submit")]
public IActionResult Submit()
{
return View("~/Views/Home/Submit.cshtml");
}
}
Test:
https://localhost:44307/Submit
https://localhost:44307/submit
The screenshot of result:
There are some articles it might help you to figure out Razor Pages and MVC.
How Does Razor Pages Differ From MVC In ASP.NET Core?
Building Your .NET App - Razor Pages vs. ASP.NET MVC

Add a #/ to the start of the url in a controller redirect in Grails 3.2.3

I am building a custom angular app in Grails, but sticking as much as possible to the default Grails Controller View behaviour.
What I'm trying to do is: using the scaffolding controller. Get the same behaviour but by ading a #/ to the start of the url. So that after you save a Record, you'd be redirected to:
http://localhost:8080/#/country/show/5
instead of
http://localhost:8080/country/show/5
So that Angular kicks in again. I know this isn't the standard Angular behaviour but I'm trying to use as few angular files as possible since I have very little knowledge in angular.
The default scaffolding redirect is:
redirect country
And I tried using:
redirect base: "#/", country
redirect country, [base: "#/"]
redirect country, base: "#/"
redirect absolute: "#/", country
But they all throw 500 error when called.
This is my current app config in angular:
app.config(function($routeProvider) {
$routeProvider.when("/:controller/:action",{
templateUrl:function(params){
return '/'+params.controller+'/'+params.action;
}
})
.when("/:controller/:action/:param",{
templateUrl:function(params){
return '/'+params.controller+'/'+params.action+'/'+params.param;
}
});
});
Have you tried this?
class SomeController {
LinkGenerator linkGenerator
def action() {
redirect uri: linkGenerator.link(
controller: 'country', action: 'show', id: 5, base: '/#')
}
}
UPDATE: Given the requirement to support multiple formats, teaching angular to work with "pretty" URLs might be the only way. Here is an example posting that has the following code:
angular.module('scotchy', [])
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl : 'partials/home.html',
controller : mainController
})
.when('/about', {
templateUrl : 'partials/about.html',
controller : mainController
})
.when('/contact', {
templateUrl : 'partials/contact.html',
controller : mainController
});
// use the HTML5 History API
$locationProvider.html5Mode(true);
});
I ended up giving up on angular entirely. To show the views inside a dialog I just extract the html segment from the response returned from the server and I get all the default behaviour that Grails includes out of the box.
Since grails is a full stack framework and it's front end is highly customizable. Unless you want to build an entire angular app it's not worth replacing the front end with angular just for it's single view capabilities.
The server responses may be slightly bigger than what I need to show inside a dialog, but it doesn't hurt performance. And the controllers don't know if their views are being rendered inside a dialog or as a full web page, which is what I wanted in the first place.

MVC5 and Angular.js routing - URLs not matching

I'm having some trouble with routing in Angular.js and MVC5. I've simplified it down to the example below.
My angular routing code is:
app.config(["$routeProvider", "$locationProvider", function ($routeProvider, $locationProvider) {
$routeProvider.when("/", {
template: "<h1>index</h1>",
})
.when("/Home/About", {
template: "<h1>about</h1>",
})
.when("/Home/Contact", {
template: "<h1>contact</h1>",
})
.otherwise({
template: "<h1>Error</h1>",
});
}]);
The MVC Home controller has a method for each, and each view has a DIV with ng-view attribute.
When I browse to either about or contact the route is still mapping to Index.
If I change the index path to :
$routeProvider.when("/Home/Index", {
template: "<h1>index</h1>",
})
then Otherwise kicks in and I see Error.
The code looks identical to other angular code I've used, and examples on the web. Any suggestions?
Updated: Thanks to the answers below. I think I didn't explain my problem well last night, the result of a long day. My problem is that I'm trying to have a mini-spa on a sub page of the site, so the route for the main page would be:
.when("/userPermissions/index", {
templateUrl: "/scripts/bookApp/userPermissions/main.html",
controller: "userPermissionController",
})
And the path of "/userPermissions/index" which would be the page provided by the server isn't being matched by the routing.
Angular is by design a Single Page Application (SPA) framework. It is designed to process requests within a single server page request, and handle route changes without making subsequent calls to the server. Hence, for every page load, the page is at the "root" of the application. or /, no matter what path was used on the server to load the page.
Subsequent page loads and routing are handled using the 'hash' notation /#/someroute in order to suppress a browser reload. Thus, the actual route being matched by the angular $routeProvider is http://example.com/#/Home/About, but this is loaded from the / server route.
If you redirect the page to /Home/About on the server, but still want to get to that match in Angular, then the route would be http://example.com/Home/About#/Home/About. Quite problematic, as you can imagine.
HTML5 Routing Mode can be used to remove the #/ from your routes, Allowing you to match http://example.com/Home/About in the Angular $routeProvider. But, for Angular to really shine, you should also configure Rewrites on your server, and not handle these Routes as separate views in your ASP.Net application. Generally, you will have a much cleaner solution if you can restrict server communications to API calls, as mixing Server HTML (or Razor) with Client Side Angular gets very confusing very fast.
I would suggest you to create one base for your angular SPA.
That means you will need to create a C# controller inside your application that will have one action i.e. Index
SPAController.cs
using System.Web.Mvc;
namespace AngularApp.Controllers
{
public class SPAController : Controller
{
public ActionResult Index()
{
return View();
}
}
}
Views/SPA/Index
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
<div ng-view></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular-route.min.js"></script>
Now all is set hit html ng-view will load partial view by watching route.
Hit in browser http://anything.com/spa/#/. Then your angular app will start working on page.
I would not suggest you to use html5mode() inside MVC app. That will create many problem inside your app. And it will take more time to manipulate things.
Thanks.

Changing URL without changing Actual Path to Redirect

I am new to ASP.Net and working on MVC 4. I want to replace my current URL with a customized URL.
For example:
Current URL: http://www.testsite.com/home?pageId=1002
Desired URL: http://www.testsite.com/1002/home/
So the URL that is displayed in the address bar will be the desired one and actual URL working will be the current one.
I have tried URL routing in Global.asax file of my project but doesn't seems to be working for me.
What exactly I want is to put the URL Like this.
Thanks in Advance.
ASP.NET MVC 4 provide a toolbox way to write your application. The URL that you see in the browser comes from Routing that do the hard work to convert url to app routes and app routes to url.
1) The default ASP.NET MVC 4 Template project comes with a file at App_Start folder named RouteConfig, where you must config the routes for the app.
2) The routes has precedence order, so, put this route before the default one:
routes.MapRoute(
name: "RouteForPageId",
url: "{pageId}/{action}",
//controller = "Home" and action = "Index" are the default value,
//change for the Controller and action that you have
//pageId is the parameter from the action that will return the page
defaults: new { controller = "Home", action = "Index" }
);
Now you can enter myappdomain/1220/index for exemple.
Hopes this help you! Take a look here for more info ASP.NET Routing!

Running ASP.NET MVC in a subdomain makes Html.ActionLink render broken links

I am running MVC in a subdomain
http://test.domain.com which points to the /Test directory on my webhost4life account.
Html.ActionLink("About", "About", "Home")
it renders a link to
http://test.domain.com/Test/Home/About -- which gives a 404
the link should be ..
http://test.domain.com/Home/About
is there a way to override ActionLink to omit the /Test on render?
Thank you
Experiment 1
I added a route to the table like this...
routes.MapRoute(
"Test", // Route name
"Test/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
and now action link renders links like this..
http://test.domain.com/Test/Test/Home/About/
when this is clicked it does not give a 404 but gives the Home controler About action.
Result
No more broken links but the site renders ugly urls.
For a site using lots of subdomains I use a nifty MVC extension from ITCloud called UrlRouteAttribute. It allows you to assign a route to every action as an attribute setting the path and name. I have extended this to allow fully qualified paths - so to include the domain/subdomain the controller should attach to. If this is something you'd be interested in I'll upload a copy somewhere.

Resources