.NET MVC and Angular with ui-router - asp.net-mvc

I have a scenario where I am using .NET MVC to serve up an initial page 'index.cshtml' which then delivers all the Angular components required to run a single page app.
For routing, I am using the excellent ui-router component by the Angular-UI team, and for the most part it works well.
My issue is with the very first page load. When browsing to the site, it doesn't go to the very first state/url. It just loads up my 'shell' with no content. My app config code looks like this:
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: "/home",
views: {
"content": {
templateUrl: "app/dashboard/dashboard.html",
controller: 'DashboardController'
},
"subNav": {}
},
});
If I click around the navigation (generated by ui-sref attributes) everything works fine. It's only the first page load.
My first thought was that it was the .NET MVC routing that is somehow borking up the first request, so I think I've disabled it by changing the default route to the following:
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
But I can't be sure this has done what I wanted it to do. It certainly didn't fix my issue.
Any ideas?

Your angular code looks good to me. I have the exact same code on my project and when I hit / I get redirected to /home.
It might be that the template url is not accessible because of ASP.Net MVC router.
Other tips:
Make sure that when you refresh the page on /home it works correctly
Make sure you are adding the DashboardController to y our app module.
Manually hit app/dashboard/dashboard.html to check if you can get the template.

I think you have to actively set a route for otherwise to be used.
You can solve the problem by setting the state in the run block and handle the $stateChangeError.
app.run(['$rootScope','$state',function($rootScope,$state) {
$state.transitionTo('home');
$rootScope.$on('$stateChangeError',
function(event, toState, toParams, fromState, fromParams, error){
$state.transitionTo('home');
});
}]);

A more radical alternative is to remove your reliance on .net MVC to serve up any pages. You could then move all your server side code into a .net webApi for a reuseable api including all security etc. (although you should replicate your security in your front end also). Your Angular app with ui-router would then be responsible for all navigation and routing. Makes it less complex in my opinion. No need to mix an angular SPA and MVC. All the features in MVC such as bundling/minification/routing etc can be done in your front end angular app using bower/grunt/gulp packages and configuration. Just requires you to do a bit more reading...leaves you with a cleaner less complex solution and only and index.html and associated assets to deploy (alongside your Webapi which you can re-use). To do this you can create a web project (non MVC) add an index.html and off you go. If you want to add in Modern Web development techniques you can use one of the .net vNext web application templates which allows you to integrate with npm/gulp/grunt/bower. Microsoft have already built this in. Deployment can ignore the vNext project and just work on the html/js/assets. Productivity enhancements from the vNext project, yet simplicity from losing MVC.

Related

How can I create a Vue sub-site or route handler within an ASP.NET MVC (non core) app?

I maintain an ASP.NET MVC web application that uses the conventional MVC architecture except for any route that starts with /admin, which is handled by an older WebForms architecture. The MVC and WebForms code coexist in the same .NET 4.8 Framework project, and the user of the site can't even tell there's any difference, because the styling is the same and we use url prettifying tricks so that you can request /admin/something rather than /admin/Something.aspx.
This all works fine, except that WebForms is really showing its age and now we want to port the admin stuff to Vue. But I can't figure out how to deploy Vue such that it has the same coexistence with MVC.
I know that I could continue to use Razor pages and add Vue with a script tag, progressive enhancement style, but I think that makes it impossible to use single file components, which is one of the Vue features that seems important.
It seems like the most functional way to use Vue is to create a proper Vue site, with build step tooling, but how can I do this within an existing MVC project and just delegate one route to the new code, and port other routes over as needed?

Call controllers from one project to another project

I'm using Asp.net MVC4 with razor. I want to know how to call a controller from one project to another project in a same solution. (I'm new to MVC4)
You can simply add your controllers to another project (class lib or MVC project, etc...) We have a couple projects that share controllers(webAPI as well as MVC). I typically use area constraints for the API controllers and namespace constraints for MVC controllers- especially if you have something like a base HomeController.cs used for some projects and you want to override it in just one particular MVC application project.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Common.MVC.Controllers" }
);
The answer depends a great deal on the concrete problem you are trying to solve.
This is something important to remember when asking questions on Stack Overflow. Sometimes it's more beneficial to ask how to solve your problem rather than how to accomplish the solution you've come up with.
If your goal here is to avoid code replication the simplest answer is to add your second project as a reference to your first. Accessing the controller is still a bit difficult because you need to instantiate it properly so what I'd recommend instead is that you abstract the code you wish to avoid replicating into a third project and have both your MVC projects make calls to the utility class you've created.
Another possibility is that you'd like to have your web services interact with each other while maintaining a client/server relationship. This can be achieved by creating an HTTP web request directed at the port number that Visual Studio selects when you run the second web service project. .Net is capable of doing this but personally I recommend using RestSharp.
You have to seperate projects (because you are testing in local) and then run Destination project and get address (like http://localhost:15823/). After that,
in another project's controller, use the following:
public ActionResult Index()
{
return Redirect("http://localhost:15823/");
}
and run another project.
I kept running my other project whose links I was calling. So in short both applications must be running simultaniously.

mixed MVC routing for MVC app under web forms app

I have an instance of BlogEngine.net installed at the root of my hosted server. I wanted to play with ASP.Net MVC to write a small app and installed that app under a folder off the root.
I am able to see the http://example.com/testApp/ but the the routed pages like http://example.com/testApp/edit are giving 404's.
I have searched around and I'm just not clear what is needed to get the routing right. Do I need to set something in BlogEngine's web.config or do I need to be doing something in my applications settings?
The host is WinHost.com and it is IIS7
Edit/Update
So I understand that the http://example.com/testApp gets served because there is a default.aspx under that directory and that the routed pages don't get served because they don't have physical aspx's. The /edit gets routed to the edit view just fine when I launch it under Visual Studio.
I am guessing that the BlogEngine.net's global.asax is trying to map these pages to the BlogEngine world and not routing them to my testApp.
If that is the case then my question is how do I get BlogEngine to forward the requests to my testApp? I was hoping that I was missing something simple in the web.config because if I have to add stuff to BlogEngine's global.asax to do routing then won't I need to rebuild BlogEngine?
Based on the information I found in the MVC tutorial, I have discovered why my routing wasn't working.
My request processing mode on the hosted server was configured to use the Classic .NET AppPool not Integrated mode. To get it to work in classic mode you need to either modify the route table to use file extensions or create a wild card script map.
I was able to keep BlogEngine working using integrated mode so all that I needed to resolve this issue was to change the mode.
Hope this helps someone...
Do you have a Edit.aspx file existing in your application for your testApp controller? The way the default route works is:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
So by default, when you access Home/Index, ASP.NET MVC looks for Index.aspx
In your case, your routing consists of (I just made this up):
routes.MapRoute(
"CustomRoute", // Route name
"{controller}/{action}/{id}", // URL with parameters, id is optional.
new { controller = "testApp", action = "Edit", id = "" } // Parameter defaults
);
Where you are trying to use Edit.aspx
Inside of your Global.asax file is where all your custom routing exists, have you touched that file at all or no? The rule of thumb that I have heard about is that you want to write all the custom routing first prior to the default.
EDIT:
I also stumbled across this, might be helpful
There are four sections in the configuration file that are relevant to routing: the system.web.httpModules section, the system.web.httpHandlers section, the system.webserver.modules section, and the system.webserver.handlers section. Be careful not to delete these sections because without these sections routing will no longer work.
Taking from here
Good luck, hope this helps.

How do I set up a route for the home page of an ASP.NET MVC site?

I'm working with an ASP.NET MVC site which will use a CMS controller for all pages of the site except for the home page. Here's the idea:
Home controller:
www.site.com
www.site.com/default.aspx
CMS Controller:
www.site.com/about
www.site.com/agenda/schedule
www.site.com/monkey/eats/spaghetti
(pretty much anything else)
This page lists some options on how to set up a default page routing:
Leave Default.aspx unrouted and unredirected as the entry point to your application - with static links that take your users into the MVC portion of the app (or other static content).
Redirect Default.aspx in the code behind, either using the Page_Load event handler code, or use Response.Redirect("~/home") to send them to the Home controller (although this is a round-trip redirect).
Rename or delete Default.aspx. Despite the warning in the markup that says that default.aspx is required to ensure that ASP.NET MVC is activated by IIS when a user makes a "/" request... it's not actually needed in either the VS dev server, or IIS7. The default request will remain an application root request "/" and will be caught by the default route and sent to the home controller.
I guess one other option is to just use one controller with some logic that detects the home page case, but that seems to be fighting the concept.
How do you recommend setting up a specific route for the site home page?
www.site.com can be handled by an root map route
routes.MapRoute(
"Root",
"",
new { controller = "Home", action = "Index", id = "" }
);
Put the following in page load of Default.aspx
HttpContext.Current.RewritePath(Request.ApplicationPath, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(HttpContext.Current);
This rewrites the request to root and handled by the map route above.
BTW, you can actually find the code from the MVC template project.
If hosting on IIS7 integrated mode, I suggest just getting rid of default.aspx. As I understand it, it's only necessary for activation on IIS6 and IIS7 classic mode.
I think option #1 is easiest. I probably will stick to it until finding a strong reason to move or finding the alternative. The default template uses this approach.
[UPDATE] Canton beat me to it

Getting ASP.NET Mvc and Web Forms to work together

Sorry if this as already been asked.
I am currently working on a small feature and am trying to implement the ASP.NET Mvc framework into my current Web Forms web application. I have been following the Professional ASP.NET 3.5 Mvc Chapter 13 pdf document that I recently found on stackoverflow to get Web Forms and Mvc to work together. I have completed all three steps:
Added the references to the libraries System.Web.Mvc, System.Web.Routing, and System.Web.Abstractions
Added the two directories to my web application: controllers and views
Updated the web.config to load the three assemblies mentioned in step one and registered the UrlRoutingModule HttpModule. I also added the initial routing settings to my Global.asax file
RouteTable.Routes.MapRoute(
"Default", "{controller}/{action}/{id}", new { controller = "Support", action = "Index", id = "" }
);
Once I try and run my newly created page following the ASP.NET Mvc framework I get a NullReferenceException on the following piece of code:
<%= Html.Encode(ViewData["Message"]) %>
In my controller I have ViewData["Message"] being set to "Message!" just as a test. Have I missed something setting my web application to work with ASP.NET Mvc?
Any help would be greatly appreciated.
Thanks,
From playing with the early betas, until today, I find it easier to create a new MVC application and "import" my exsiting files into the solution than it is to get all of the settings right in an existing application. I see no reason to get hot and heavy over setting up plumbing I can have written for me from a template. Perhaps I am just too lazy.
I find that I can get "legacy ASP.NET" web forms working fine with MVC. The only dink to the whole project is getting the app routed to my default.aspx to begin with. Much easier than running through multiple steps to include MVC.
I know this is not a direct answer to your question, but I think trying it will solve your problem, as well. Another benefit is you leave the old "legacy" source in case a bug fix comes in. But, then, you should be under source control anyway.

Resources