We have an application built with ASP.NET MVC 5.
For that application, we've built several URL-related HTML helpers that act like this:
Imagine there is an anchor that leads to certain URL, i.e. /Customer/Edit/5. We have a helper that will in the background ask ClaimsAuthorizationManager (which is part of Windows Identity Foundation API) whether the current user can perform action Edit on resource Customer. If yes, HTML markup for anchor tag will be rendered. Otherwise, nothing will be rendered.
With these helpers, we've been able to have dynamic website based on background policies that define URL's user can access based on specific claims.
Now we need to push the same logic to AngularJS based SPA.
So again, goal is to skip rendering of URL-related HTML if user is not allowed to access that particular URL.
I've not been able to find any good resources on how to perform this kind of authorization with AngularJS.
Is there a proper way to do this or should I go with some custom logic?
Are there any good references that I can read on?
Angular works great in RESTful applications. In your case, you could set up your app to fetch your claims as JSON and set your angular template to render accordingly.
But you can also use MVC's helper methods on partial views and use those partials as templates for your angular application. So when your angular app fetches the html template at foo/bar/baz (via route or ng-include or directive template or whatever), your html template will come back with the MVC partial view instead of a static html file. It's a little dirty, but it works in a pinch.
Related
I'm a complete beginner with AngularJS so this may be something completely trivial. I'm building an Asp.net MVC application (really juts delivering insignificant parts) with Web API backend (including login/logout capabilities).
I'd like to use AngularJS in my application. But I have a bit of a dilemma how to slice my page into several sections that somewhat work independently. Let's say this is a simplified skeleton of my page.
Questions
How should I structure my AngularJS parts on my page?
Should I have a single ng-app for the whole page or have several non-nested ones for each individual component on my page?
In case of a single ng-app I expect to have one ng-view that would include Context and Content components.
How about client-side routing with each individual option (single/multi ng-app)?
Is this a viable approach or should I think of Angular differently and structure it differently?
I should likely have separate controllers for each individual component and a single authentication service (communicating with Web API on the server) to provide user authorized items.
What would you recommend?
Bare in mind I'm a complete beginner in AngularJS but am very versed in server side part (MVC and API).
Let me try to address some concerns
Should I have a single ng-app for the whole page or have several
non-nested ones for each individual component on my page?
There can be only 1 ng-app per SPA, so you cannot have ng-app per component. You can have module per component which can be tied into the ng-app related module.
In case of a single ng-app I expect to have one ng-view that would
include Context and Content components.
ng-view would only contain the content of the active view. It does not require to have any menus. There can be something like RootController which is container for overall app. The html would consist of the obvious ng-view and number of ng-include.
Something like
<div ng-controller='RootController'>
<div id="contextMenu"><ng-include src='contextMenuTemplate'></div>
<div id="primaryMenu" ><ng-include src='primaryMenuTemplate'></div>
<div id="secondarMenu" ><ng-include src='secondaryMenuTemplate'></div>
<div ng-view/>
</div>
In your RootController you would have some logic like
if ($route.path) {
$scope.contextMenuTemplate="path1"; //path corresponding to the route
}
Or else you can also create a object map and use that for selecting the templates
var viewTemplates= [{
path:"/home",
contextMenuTemplate:"path1",
primaryMenuTemplate:"path2",
secondaryMenuTemplate:"path3"
}]
This can now be used for selecting templates in ng-include.
How about client-side routing with each individual option (single/multi ng-app)?
Routing happens on the ng-view part only. You select other templates to load based on the primary view. You can also look at ui-router for advance routing stuff.
Update
When authentication and authorization comes into picture both the server and client play their part. Server authenticates and then can use that information for service different templates if the user is authenticated or not, and may on the same url. For example /home/leftnav can server different content based on the authenticated user. Same can be done on Angular side but this behavior can be by-passed as it is just javascript. Same holds true for api calls (using webapi) where server can decided what to send back.
On client side user state can be tracked using a service\factory. A service like UserService with methods\properties like CurrentUser can provide details on the current logged in user and can be injected into any directive, filter, controller which as to make decision based whether and what user is logged in..
I have a asp.net mvc4 web application which for example allows me to manage members and member resources to the site.
On the member's home page there are several different sections of details about their profile. I want to use angular.js and webapi(entityframework) to allow them to edit their address details in place and save them without a page postback. I imagine the best place to start is to have a partialview which displays these address details as part of the main page view.
Are there any examples of such a setup?
You can definitely do this. First, for switching the details based on which section the user selects you have two options:
1) Create a module and setup routes. The routes will allow you to have a base HTML page with an area where you can switch partial HTML 'views' in and out based on the URL that you are clicking on in the application. The AngularJS site has a tutorial where they do something similar. Pay notice to the ng-view explanation.
2) You can create custom directives and fetch an external HTML partial page. In the directive you 'compile' the HTML partial which allows you to use any directives that are on that page (ng-click, ng-class, etc) and then render it where the div is declared in the original page. This is a bit more advanced, so look at the ng-view example first.
For sending the data back to the mvc application, all you need to do in angular is declare a resource with the url back to the mvc app where you post the data and then send it some data. Something like this:
$resource('api/updateUserData',
{userName: userNameVar, userEmail: userEmailVar},
function(data){
//callback code where you do something with the returned data if any
}
);
There is a nice github project called angular-app that has a basic CRUD setup, shows you how to layout the angular app itself, how to use tests, how best to structure the angular files, etc. This may also be a bit more than you need for this small project, but it can at least give you some ideas on how to move forward if your app grows.
TL;DR
What are the best practices when using .NET Razor views and AngularJS?
Context
We are developing a public website (not an intranet application) using mvc4 with razor, and we weren't very familiar with client script, so we started with what we knew: jQuery.
But now things are getting more complicated and we'd like to switch to AngularJS.
On the .NET part, we use Razor templates and UIHintAttribute (plus some custom ones) to render the right html "control". We also add custom html attributes to give extra information to the jQuery part (like title for a tooltip....)
So we already use a declarative way of setting the user interface behavior, that's why AngularJS seems a good option.
Questions
Since we already have models defined server side, and since AngularJS also uses models, wouldn't it force us to duplicate code?
How do we deal with data binding feature, since we already do some binding server side (in the views). Should we make a completely asynchronous application, making AJAX calls from AngularJS to load data, or can we mix both?
Anything else we should be aware of when trying to use both of these technologies?
I did some research on Google, but I can't find detailed ways of mixing Razor views and templates with AngularJS... Perhaps that's just not a good thing to do?
We dealt with this issue for months when working with MVC plus another JavaScript framework (Knockout). Ultimately, if you're going to be using a client-side MV* framework for rendering your user interface, you will find that mostly ditching Razor is going to be your best bet.
Most of the major MV* JavaScript frameworks, including AngularJS, assume you will be maintaining UI state and rendering your user interface based on JavaScript models or view models. Trying to mix in server-side rendering is just not going to work very well.
That's not to say there is no use for MVC when it comes to developing an Angular application. You can still take advantage of some great features like ASP.NET Bundling and Minification. And sometimes it works really well to embed JSON directly into the page using a Razor view or partial as opposed to making an additional AJAX call.
As for models, you may want to take a look at Breeze.js. It's a JavaScript library for data access that goes great with ASP.NET on the server side to share model metadata.
We wrote our own data binding mechanism that synchronizes the angular.js model with a view model on the server side. The javascript model is generated from a JSON serialization of the server-side view model to avoid the duplicate code that you were talking about.
We are using SignalR to update the client's view model from the server.
Server-side changes of the C# view model properties are sent to the client as a packet containing the path to the property, e.g. Persons[42].Address.City, and the value itself, e.g. New York. The view model inherits a base class that takes care of generating the property path, so the actual view model looks quite clean and we can concentrate on business logic.
Client-side changes of the javascript view model properties are sent to the server in the same way. To catch the change events, we encapsulate all fields of the original javascript model in get/set properties where the setter sends the update packet to the server.
Server-side methods of the view model can be invoked in a similar way. All objects in the view model have an invokeMethod function that can be used like this: Products[42].Manufacturer.invokeMethod('SendEmail', 'mailsubject', 'mailbody'). This will send a packet to the server containing the method path Products[42].Manufacturer.SendEmail and the arguments as an array of ['mailsubject','mailbody'].
In conclusion, the html view (kind of) binds to the view model on the server side where other systems, such as regular Razor views can work on the same objects.
The source code can be found here: SharpAngie.
Is there any sane way to use these?
What I want to have - is a single page with a nav-menu and <ng-view> below it.
And all the routing should be angular's responsibility.
But, I'd like to keep mvc goodness as well. I like neatly organized server-side controllers and razor pages.
I can't access .cshtml directly though, so how do I access my templates?
I don't want the main page and its content to be reloaded ever. It loads once and after that, all the navigation to other pages should be loading associated templates only.
How can I achieve that?
I can't find a single thorough example how to use them together.
Angular is used for single page web applications (SPAs).
ASP.NET MVC is used for server-side pages.
In ASP.NET MVC with Angular, your Index.cshtml or whatever your main view page is will contain all your JavaScripts and load your Angular app. You shouldn't ever navigate away from that page again. Angular's router just changes the URL (using a hash) and rebuilds the DOM based on the route.
They aren't supposed to "work together" for navigation. The only way they work together is if you create a REST API (or any API I suppose) with MVC and access it through Angular ($http, $resource, etc).
Checkout this project https://github.com/kazimanzurrashid/my-walletz-angular/blob/master/source/MyWalletz/Views/Home/Index.cshtml#L11 (shameless plug i am the owner) there is a helper method called IncludeClientView which inlines all the client side templates in the view. If you want to dynamically load the templates then create a controller and pass the template name from the client, then in the controller use partial view to return the template.
please install the AngularJS SPA Template from visual studio>> extensions and updates .
i have to create a new asp.net mvc page that integrates content provided by a cms on the server side static. my mvc page provides a masterpage with the navigation and certain links should point to pages of the cms (which is installed on the same server). it should be something like a "server side iframe".
my idea is to create a controller which loads the page of the cms using a webrequest, extracts the body part of the page and passes the extracted data to the view. the view simply outputs the passed html. i also plan to add some logic to pass post requests to the cms (for news letter subscriptions, contact forms, ...)
now my question is: is it possible to implement this solution? or is there a better way to do this on the server side?
Could you use Application Request Routing to just hand off requests to your CMS, or do you need to include the externally provided content within an existing masterpage?
If you need to use the masterpage I would stick to the solution you suggest, although I might investigate the most robust and efficient option for querying the content from the CMS and perhaps if caching would be a good option.
It is undoubtedly possible, but keeping track of users, authentication, cookies etc. seems like a really tedious job. Also, embedding css classes, hard-coded styling etc. from the CMS in your MVC site could give you a severe headache.
If the CMS isn't home-brewed it probably has an API. In that case I would much prefer to use the API to get at the data I needed and then render that data using pure MVC. This will give you a much cleaner and more stable integration with the CMS.