Application examples of integrated Angularjs in asp.net MVC

Source: Internet
Author: User
Tags foreach bind naming convention object model static class versions angularjs examples sql server express

Introduced

When it comes to the development of computer software, I want to use all the latest technology. For example, the front-end uses the latest JavaScript technology, and the server side uses the latest REST-based Web API service. In addition, there is the latest database technology, the latest design patterns and technology.

Several factors are at work when choosing the latest software technology, including how to integrate these technologies. One of my favorite technologies over the past two years has been to design a single page application (SPA) Angularjs. As a Microsoft stack developer, I am also a fan of implementing MVC design patterns and research with the ASP.net MVC platform, including its bundling and compression capabilities, and the implementation of its WEB API controller for RESTful services.

In order to both, this article describes the solution of integrating angularjs in asp.net MVC.

Due to the length of this article, it will be divided into 3 chapters, respectively introduced.

Overview


The WEB application for the example in this article will have three goals:

Implement ANGULARJS and JavaScript ANGULARJS controllers in the front-end page
Use Microsoft's ASP.net MVC platform to build, guide, and bundle an application
Dynamically loading ANGULARJS controllers and services according to the requirements of functional models
The sample application in this article will contain three main folders: the home folder for contacts and indexes, allows you to create, update and query customer folders for customers, allows you to create, update, and query product folders.

In addition to using Angularjs and ASP.net MVC, this application will also implement Microsoft's ASP.net Web API service to create RESTful services. Microsoft's Entity Framework will be used to build and update a SQL Server Express database.

This application will also use some dependency injection using Ninject. In addition, fluent interface and lambda expressions are used to incorporate a small authentication library called Fluentvalidation to build validation business rules that reside in the application business layer.

Angularjs VS asp.net Razor view
For years, I've been using the full Microsoft asp.net MVC platform to develop WEB applications. The ASP.net MVC platform uses the Razor view, compared with the traditional asp.net Web form's postback model. This leads to a separation of concerns between appropriate business logic, data, and presentation logic. After MVC has been developed with its conventions over configuration and simple design patterns, you will never want to go back to developing Web forms.

The ASP.net MVC platform and its Razor view engine are not only simpler than Web forms, but also encourage and allow you to mix. NET server-side code and styles. The HTML-mixed. NET code in the Razor view looks like a casing code. In addition, in the ASP.net mvc pattern, some business logic can be eventually written to the controller of MVC. In the MVC controller, it is tempting to write code to control the information in the presentation layer.

ANGULARJS provides the following enhancements to the Microsoft ASP.net MVC Razor view:

The Angularjs view is pure HTML
The Angularjs view is cached on the client for faster response and does not produce a server-side response at each request
ANGULARJS provides a complete framework for writing high-quality client-side JavaScript code
ANGULARJS provides a complete separation between the JavaScript controller and the HTML view

asp.net MVC Bundle and compression
Bundling and compression are two techniques you can use to shorten the time required to load a WEB application. This reduces the request load time (such as CSS and JavaScript) by reducing the number of requests to the server and reducing the size of requests. Compression technology also makes it harder for others to hack into your JavaScript code through complex code logic.

When it comes to bundling and angularjs frameworks, you'll find that frameworks such as grunt and Gulp are automatically used during bundling and compression, and grunt and Gulp technologies are a popular web library with Plug-ins that allow you to automate every job you do.

If you're a Microsoft developer, you can use them to publish your Web apps one-click in Visual Studio without learning to use any of the third tools and library classes. Fortunately, bundling and compression is a feature in ASP.net 4.5 asp.net that can easily be merged or bundled into a single file. You can create css,javascript and other packages. Fewer files means fewer HTTP requests, which can also improve the load performance of the first page.

Using Requirejs to implement dynamic loading of MVC bundles
When developing a ANGULARJS application, one of the things is not certain. Because the application will start to be booted and downloaded, ANGULARJS will request all JavaScript files and controllers when the main page is indexed. This may not be ideal for large-scale applications that may contain hundreds of JavaScript files. Because I want to use the asp.net bundle to load all the ANGULARJS controllers. Once the index is started, a huge challenge in a asp.net bundle will appear on the server side.

To implement the example program dynamically binding asp.net packages, I decided to use the Requirejs JavaScript library. Requirejs is a well-known JavaScript module and file loader, and the latest version of browsers support Requirejs. At first it seemed like a simple thing to do, but over time, I did a lot of coding, but I didn't solve the problem of using server-side rendered bundle and client Angularjs technology.

In the end, after a lot of research and trial and error, I came up with a small number of code but a proven solution.

The next section of this article will show you the process of integrating angularjs in asp.net MVC.

Create an MVC project and install the angular NuGet package
To start the sample application, I created a asp.net MVC 5 Web application by selecting the ASP.net Web Application template in the Visual Studio 2013 Professional Edition. After that, I chose the MVC project and used the MVC Web API to add folders and references in my application. The next step is to download and install NuGet Angularjs by selecting "Manage NuGet Package Solutions" in the Tools menu.

For this sample application, I have installed all of the following NuGet packages:

Angularjs-Install the entire ANGULARJS library
Angularjs Ui-angularjs Framework's Companion suite UI tools and scripts.
Angularjs UI Boot-contains a set of native ANGULARJS directives for boot tags and CSS
Angularjs block Ui-angularjs blockui instruction, block request in HTTP
Requirejs-requirejs is a JavaScript file and module loaded
Ninject– provides dependency injection to support MVC and MVC Web API support
Entity Framework-A new application of Microsoft's recommended data access technology
Fluent validation-establishes a. NET validation library for validation rules.
Graceful Fonts-CSS can be immediately customized to the upgradeable vector icon
NuGet is a good package manager. When you use NuGet to install a package, it will copy the library files to your solution and automatically update the references and configuration files in the project. If you delete a package, the NuGet will leave no trace on the deletion process.

Beautiful URLs.
For this sample application, I want to implement a graceful URL in the browser's address bar. By default, Angularjs routes the URL with the # tag:

For example:

http://localhost:16390/
Http://localhost:16390/#/contact
Http://localhost:16390/#/about
Http://localhost:16390/#/customers/CustomerInquiry
Http://localhost:16390/#/products/ProductInquiry
By turning to Html5mode and setting basic URLs, you can easily clear URLs and remove # from URLs. In HTML5 mode, ANGULARJS's $ location service interacts with the browser URL address that uses the HTML5 History API. The HTML5 History API is a standard way to manipulate browser history through scripting, which is the key to implementing a single page application.

To turn on Html5mode, you need to set the $locationProviderhtml 5Mode to true during angular configuration, as follows:

Codeprojectrouting-production.js
Angular.module ("CodeProject"). config (' $locationProvider ', function ($locationProvider) {
$locationProvider. Html5mode (True);
}]);
When you use the Html5mode configuration $locationProvider, you need to use the href tag to specify the base URL for the application. The base URL is used to troubleshoot all relative URLs throughout the application. You can set the base URL for the header portion of the master page as shown below in the application:

<!--_layout.cshtml-->
<basehref= "http://localhost:16390/"/>
For the sample application, I store the base URL in a Web configuration file in a program setting. This is the best way to make the base URL a configuration so that you can set the base URL to a different value depending on the environment, configuration, or site of the application you are developing. In addition, when you set the base URL, make sure that the base URL ends with "/" because the base URL will be the prefix for all addresses.

<!--Web.config.cs-->
<appsettings>
<addkey= "BaseURL" value= "http://localhost:16390/"/>
</appsettings>
After opening the Html5mode and setting the base URL, you need to end with the following graceful URL:

http://localhost:16390/
Http://localhost:16390/contact
Http://localhost:16390/about
Http://localhost:16390/customers/CustomerInquiry
Http://localhost:16390/products/ProductInquiry

Directory Structure and configuration
By convention, an MVC project template requires that all Razor views reside in the View folder; All JavaScript files reside in the script folder; All content files reside in the content folder. For this sample application, I want to put all the angular views and the associated angular JavaScript controllers in the same directory. Web-based applications can become very large, and I don't want related functionality to be stored in different folders across the entire application's directory structure.

In the sample application, two Razor views are used, index.cshtml and _layout.cshtml master page layouts, which two Razor views will be used to boot and configure the application. The remainder of the application will include the Angularjs view and the controller.

For the sample application, I created two additional folders under the View folder, a subfolder of a customer, a subfolder of a product. All customers ' angular views and controls reside in the customer subfolder, and angular views and controls for all products reside in the Product subfolder.

Because the angular view is an HTML file, and the angular controller is a JavaScript file, from the Views folder to the browser, ASP.net MVC must be configured to allow access and delivery of HTML files and JavaScript files. This is a asp.net MVC default convention. Fortunately, you can change this convention by editing the Web.config file under the view file and adding an HTML and JavaScript processor, which will enable these file types to be delivered to the browser for resolution.


<!--web.config under the Views folder-->
<system.webserver>
<addname= "Javascripthandler" path= "*.js" verb= "*" precondition= "Integratedmode"
Type= "System.Web.StaticFileHandler"/>

<addname= "Htmlscripthandler" path= "*.html" verb= "*" precondition= "Integratedmode"
Type= "System.Web.StaticFileHandler"/>
</system.webserver>


Application version automatic refresh and engineering build
For this sample application, I want to track the version and build number of each compilation and use the AssemblyInfo.cs file's information to test and publish the application under the Properties folder. Every time the application runs, I want to get the latest version of the application and use the version number to implement the latest HTML file and JavaScript file generation, help the browser from the cache, get the latest files to replace those old files.

For this application, I use the Visual Studio 2013 Professional Edition, which makes it all simpler, and I downloaded an automatic version of the plugin for Visual Studio2013 Professional Edition

Https://visualstudiogallery.msdn.microsoft.com/dd8c5682-58a4-4c13-a0b4-9eadaba919fe

It automatically refreshes the versions of C # and vb.net projects. Download the installation plug-in to the Tools menu named Automatic Version settings. The plugin comes with a configuration tool that allows you to configure the major and minor version numbers to automatically update AssemblyInfo.cs files each time you compile. Currently, this plugin is only supported in the Visual Studio 2013 Professional Edition, or you can manually update the version number or use Microsoft TFS to manage your version number in a way that continues to build and configure the management environment.

The following is an example of using the updated assemblyversion and assemlyfileversion numbers, which are automatically updated by Plug-ins after version compilation.


AssemblyInfo.cs
Using System.Reflection;
Using System.Runtime.CompilerServices;
Using System.Runtime.InteropServices;

[Assembly:assemblytitle ("Codeproject.portal")]
[Assembly:assemblyproduct ("Codeproject.portal")]
[Assembly:assemblycopyright ("Copyright &copy; 2015 ")]

The following GUID is for the ID of the typelib if this project was exposed to COM
[Assembly:guid ("1D9CF973-F876-4ADB-82CC-AC4BDF5FC3BD")]
Version information for a assembly consists of the following four values:

Major Version
Minor Version
Build number
Revision

Can specify all the values or your can default the Revision and build Numbers
By using the ' * ' as shown below:

[Assembly:assemblyversion ("2015.9.12.403")]


Use angular view and controller replacement contact us and about Razor view
One of the first things you need to do to use the MVC project is to use the Angularjs view and controller to replace the contact us and the Razor view. This is a good starting point to test whether your configuration will allow ANGULARJS to be established and run normally. Then, if you don't need these pages, you can delete the view and the controller about and contact us.

This way of creating a controller Angularjs is implemented by injecting $scope. The view and controller of the sample application use the "controller as" syntax. Instead of using the $scope in the controller, this syntax simplifies the syntax of your controller. When you declare a controller with a "controller as" syntax, you get an instance of the controller.

Using the "controller as" syntax, all of your properties connected to the Controller (view mode) must be prefixed with the alias of your view. In the following view code fragment, the attribute header is preceded by a "VM" Alias.

<!--aboutcontroller.js-->
<div ng-controller= "Aboutcontroller as VM" ng-init= "Vm.initializecontroller ()" >

</div>
When the controller constructor is invoked, the "controller as" syntax is used, and the controller example called "This" is created. You do not need to use the $scope variables provided by angular, you simply declare a VM variable and assign "this" to it. All variables assigned to the VM object are replaced $scope. With variables assigned to the example of the controller function, we can use these aliases and access those variables.

In addition, all the controllers in the sample application are running in a strict mode using the use strict JavaScript command. This rigorous pattern makes it easier to write "safe" JavaScript code. Strict mode has made the previous "not strict grammar" a real mistake. As an example, in general JavaScript, an error-input variable name creates a new global variable. In strict mode, this throws an error, so you cannot accidentally create a global variable.


Aboutcontroller.js
Angular.module ("CodeProject"). Register.controller (' Aboutcontroller '),
[' $routeParams ', ' $location ', function ($routeParams, $location) {
{
"Use strict";
var vm = this;

This.initializecontroller = function () {
Vm.title = "About Us";
}
}]);

As mentioned earlier, one of the advantages of using ANGULARJS views and controllers in the MVC Razor view is that angular provides a good mechanism for writing high-quality JavaScript modules, a pure HTML view, and a completely separate compilation between JavaScript controllers Code way. You no longer need to use ANGULARJS bidirectional data binding technology to parse the browser's file object model, which allows you to write the JavaScript code for unit tests.

As a footnote, you will see a method named Register.controller in Aboutcontroller. Later in this article, you'll see where the registration method comes from and what it does.


Razor View and MVC route for home page indexes
An interesting thing about integrating Angularjs in asp.net MVC is how the application actually starts and implements the route. When you start the application, ASP.net MVC will enter and view the routing table in the following default manner:


//RouteConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using system.web;
using SYSTEM.WEB.MVC;
using System.Web.Routing;

Namespace Codeproject.portal
{
    publicclass routeconfig
    {
        publicstaticvoid registerroutes (routecollection routes)
         {
          routes. Ignoreroute ("{resource}.axd/{*pathinfo}");
          routes. Maproute (
          name: "Default",
           URL: ' {controller}/{action}/{id} ',
           defaults:new {controller = "Home", action = "Index", id = urlparameter.optional}
   &nb sp;     );
       }
   }
}

At the start of the application, the configuration in the MVC routing table configured in the out of place will route the application to the MVC home controller and execute the indexing method on the host controller. This will pass the index.cshtml MVC Razor view to the user output's master page content in the form of the MVC default engineering template.

The goal of this application is to replace all MVC views with the angular view. The problem is that even before Angularjs is started, the Razor View index of the home page has been executed and injected into the _layout.cshtml home page.

Since I decided to change the main page to Angularjs view, I deleted all the contents of the index Razor view using the div tag that contains the ANGULARJS ng-view tag.

<!--index.cshtml-->
<divng-view></div>
The Angularjs Ngview tag is a directive that complements $route service in a way that renders the current routed template as a home page layout. I have two choices, either embedding Ng-view code directly into the master page _layout.cshtml or injecting it into the master page using the Razor view. I decided to simply inject the label from the indexed Razor view. Essentially, an indexed Razor view is used simply during the boot process of an application and is not referenced after the application is started.

Once the application is booted and started, Angularjs will execute its own routing system and configure it in the routing table to perform its own default route. Based on this, I created a indexcontroller.js file with a separate Angularjs index.html and home page.

<!--index.html-->
<divng-controller= "Indexcontroller as VM" ng-init= "Vm.initializecontroller ()" >
</div>
When the view loads, the indexed angular view performs the initialization of the index controller through the NG-INIT directive.


Indexcontroller.js
Angular.module ("CodeProject"). Register.controller (' Indexcontroller '),
[' $routeParams ', ' $location ', function ($routeParams, $location) {
"Use strict";
var vm = this;
This.initializecontroller = function () {
Vm.title = "Home Page";
}
}]);


RouteConfig.cs
One of the first things that will happen when developing a ANGULARJS application is that you need to first develop a page that is like Customerinquiry residing in a routing file

/views/customers/customerinquiry

When you are looking for this view in the HTML page, click the Run button in Visual Studio to execute the page directly, and MVC will execute and try to find an MVC controller and view for customer routing. What will happen is that you will get an error called a view or controller that cannot find the route.

You will of course encounter this error, because the/view/customers/customerinquiry route is a angular route, not an MVC route. MVC does not know this route. If you also want to run this page directly, you need to address this problem by adding additional routes to the MVC routing table to tell MVC to route all requests to the MVC master and render the razor view and route the application through routing.

Since I have three view folders, home folders, customer folders, and product folders, I added an MVC routing configuration class to route all requests to primary/index routes. Clicking F5 when the application is running also goes into the MVC routing table. In terms of angular and how a single page works, when you click F5, basically you restart the Angularjs application.

With these additional routes, it is now possible to execute the ANGULARJS route directly. You can handle your route with a wildcard route in the MVC routing table, but I prefer to use an explicit routing table and allow MVC to reject all invalid routes.

The basic thing to remember is that the MVC route will occur before Angularjs starts, and once the boot starts, ANGULARJS will take over all subsequent routing requests.


RouteConfig.cs
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Web;
Using SYSTEM.WEB.MVC;
Using System.Web.Routing;

Namespace Codeproject.portal
{
Publicclass Routeconfig
{
Publicstaticvoid registerroutes (routecollection routes)
{

Routes. Ignoreroute ("{resource}.axd/{*pathinfo}");
Routes. Maproute (
Name: "Homecatchallroute",
URL: "home/{*.}",
defaults:new {controller = "Home", action = "Index",
id = urlparameter.optional}
);
Routes. Maproute (
Name: "Customerscatchallroute",
URL: "customers/{*.}",
defaults:new {controller = "Home", action = "Index",
id = urlparameter.optional}
);

             routes. Maproute (
             Name: " Productscatchallroute ",
             URL:" products/{*.} ",
             defaults:new { Controller = "Home", action = "Index",
             id = urlparameter.optional}
            );

Routes. Maproute (
Name: "Default",
URL: ' {controller}/{action}/{id} ',
defaults:new {controller = "Home", action = "Index",
id = urlparameter.optional}
);
}
}
}


$ controllerprovider and dynamic load controllers
When the sample application is started, the application will preload the application's core controllers and services. This includes all the controllers in the home directory and shared services for the application.

The shared services for this application will be performed in all modules-including an Ajax service and a reminder service. As mentioned earlier, this application has three functional modules: basic about, contacting us and homepage module, a customer module and product module.

Since this application can grow over time, I don't want to preload all of the functional modules in the configuration and boot phase of the application. After the application starts, I only want to load these controllers and product modules when the user requests it.

By default, Angularjs is designed to preload all controllers. A typical controller looks like this:


Aboutcontroller.js
Angular.module ("CodeProject"). Controller (' Aboutcontroller '),
[' $routeParams ', ' $location ', function ($routeParams, $location) {
"Use strict";
var vm = this;
This.initializecontroller = function () {
Vm.title = "about";
}
}]);

If you try to load the controller dynamically after the configuration phase, you will receive a angular error. What you need to do is to use the $controllerProvider server to dynamically load the controller after the configuration phase. Angular uses $controllerProvider service to create a new controller. This method allows registration of the controller by registering the method.


Aboutcontroller.js
Angular.module ("CodeProject"). Register.controller (' Aboutcontroller '),
[' $routeParams ', ' $location ', function ($routeParams, $location) {
"Use strict";
var vm = this;
This.initializecontroller = function () {
Vm.title = "about";
}
}]);

The above controller is modified to execute the $controllerProvider register method. For this registration method to be valid, this registration must be configured in the configuration phase. The following code fragment uses $controllerProvider to make the registration method valid after the application is started. In the following example, a registration method for registering and dynamically loading two controllers and services is provided. If you wish, you can also include the registration function for all libraries and angular.


Codeprojectbootstrap.js
(function () {
var app = Angular.module (' CodeProject ', [' Ngroute ', ' ui.bootstrap ', ' ngsanitize ', ' Blockui ']);

App.config ([' $controllerProvider ', ' $provide ', function ($controllerProvider, $provide) {
App.register =
{
Controller: $controllerProvider. Register,
Service: $provide. Service
}
}
}

The above is how to integrate the first part of Angularjs in ASP.net MVC, the following content will be presented in the latter two articles of this series, please look forward to!

Through the first part of the learning, I believe that we have to achieve in asp.net MVC integration Angularjs Basic ideas have some understanding. When we start with ASP.net MVC and angularjs, we can leverage development tools to help the development process. asp.net MVC development, you can use the lightweight control of ComponentOne studio asp.net mvc, seamless integration with Visual Studio, fully compatible with MVC6 and ASP.net 5.0, and will significantly increase productivity; Ang ULARJS development, you can use the WIJMO for enterprise application development to launch a series of HTML5 and JavaScript development control set, whether the application is mobile end, PC side, or must support IE6,WIJMO can meet the requirements.

asp.net bundle and compression
The bundling and compression of CSS and JavaScript is one of the most popular and effective features of ASP.net MVC. Bundling and compression reduce the size of HTTP requests and payloads, resulting in faster and better execution of ASP.net MVC sites. There are many ways to reduce the size of CSS and JavaScript merges.

Bundling makes it easy to combine or bundle multiple files into a single file. You can create css,javascript and other packages. Compression can optimize scripts and CSS code, such as removing unnecessary spaces and annotations, shortening variable names to one character. As bundles and compression reduce the size of your JavaScript and CSS files, the HTTP bytes sent are also significantly reduced.

When configuring a package file, you need to consider a bundle policy and how to organize your package files. The following Bundleconfig class is the built-in ASP.net bundle feature configuration file. In the Bundleconfig class, I decided to organize my files through a functional module. I set up a separate bundle for each file in the project, including a separate bundle of scripts, angular core files, shared JavaScript files and home directories, customer directories, and product catalogs.

I created a separate package for the customer and the product catalog, with the idea that when the user requests these source files for the application, they should load these bundles dynamically. Since Angularjs is a pure client framework that can dynamically load asp.net and server-side technologies, the combination of these two technologies has become the biggest development challenge for instance applications that require the release of debugging modules.


BundleConfig.cs
Using System.Web;
Using System.Web.Optimization;

public class Bundleconfig
{
For more information on bundling, visit http://go.microsft.com/fwlink/?LinkId=301862
public static void Registerbundles (Bundlecollection bundles)
{
Bundles. ADD (New Scriptbundle ("~/bundles/jquery"). Include (
"~/scripts/jquery-{version}.js"));

Bundles. ADD (New Scriptbundle ("~/bundles/bootstrap"). Include (
"~/scripts/bootstrap.js",
"~/scripts/respond.js"
));

        bundles. ADD (New Stylebundle ("~/content/css"). Include (
           "~/content/bootstrap.css",
            "~/content/site.css",
            "~/content/sortablegrid.css",
            "~/content/angular-block-ui.min.css",
            "~/content/font-awesome.min.css"
       ));

        bundles. ADD (New Scriptbundle ("~/bundles/angular"). Include (
           "~/scripts/angular.min.js",
            "~/scripts/angular-route.min.js",
            "~/scripts/angular-sanitize.min.js",
            "~/scripts/angular-ui.min.js",
            "~/scripts/angular-ui/ui-bootstrap.min.js",
            "~/scripts/angular-ui/ui-bootstrap-tpls.min.js",
            "~/scripts/angular-ui.min.js",
            "~/scripts/angular-block-ui.js"
       ));

Bundles. ADD (New Scriptbundle ("~/bundles/shared"). Include (
"~/views/shared/codeprojectbootstrap.js",
"~/views/shared/ajaxservice.js",
"~/views/shared/alertservice.js",
"~/views/shared/datagridservice.js",
"~/views/shared/mastercontroller.js"
));

Bundles. ADD (New Scriptbundle ("~/bundles/routing-debug"). Include (
"~/views/shared/codeprojectrouting-debug.js"
));

Bundles. ADD (New Scriptbundle ("~/bundles/routing-production"). Include (
"~/views/shared/codeprojectrouting-production.js"
));

Bundles. ADD (New Scriptbundle ("~/bundles/home"). Include (
"~/views/home/indexcontroller.js",
"~/views/home/aboutcontroller.js",
"~/views/home/contactcontroller.js",
"~/views/home/initializedatacontroller.js"
));

 
Bundles. ADD (New Scriptbundle ("~/bundles/customers"). Include (
"~/views/customers/customermaintenancecontroller.js",
"~/views/customers/customerinquirycontroller.js"
));

 
Bundles. ADD (New Scriptbundle ("~/bundles/products"). Include (
"~/views/products/productmaintenancecontroller.js",
"~/views/products/productinquirycontroller.js"
));
}
}

Caching and ASP.net bundling
The advantage of using asp.net bundling is its "cache busting" helper method, and once you change the way CSS and JavaScript are cached, this approach will use automatic booting to make bundled files easier to cache. The following code example is executed in a Razor view of MVC (typically, on a _layout.cshtml master page). The Scripts.render method is rendered at the client, and when executed in debug mode, it produces the virtual path of the package and the sequence number of the end package. When you change the contents of the package and republish your application, the package will generate a new version number that helps the browser cache on the client and generate a new download package.

_layout.cshtml
@Scripts. Render ("~/bundles/customers")
@Scripts. Render ("~/bundles/products")
The Scripts.render feature is a good feature, but in this sample application, I want to use dynamically loaded clients and products on the client side, so I can't render some of my packages with render functionality, which is the beginning of the challenge. The question is how to use ANGULARJS to render the server-side asp.net package from client JavaScript?

_layout.cshtml-server-side boot code
One advantage of using asp.net MVC to boot a ANGULARJS application is that you can load and execute ANGULARJS code by _layout.cshtml the server-side code in the home page. This is the first step to help solve my dilemma of rendering server-side bundling through client code. Of course, you can simply embed the script to mark the client's code, but I need a way to render a package and reference, and maintain the automatic version number of the destination appended to the cached package.

At the beginning, I wrote some server-side code at the top of the _layout.cshtml master page. The first two things I do is get the application's serial number from the assembly information class, and get the basic URL for the retrieval from the application settings. Both will be parsed by the Razor view engine in later HTML.

The following code snippet produces some packages that I want to dynamically load on demand, and I don't want to load all the upfront packages when the application starts. The most important piece of information I need is a virtual path and a long version number for each bundle. Fortunately, the method of accessing bundled information is itself a bundle of functionality.

The key line in the following line of code references the bundletable. This line of code executes the Resolvebundleurl, returning the virtual path of the method and the bundle and version number of each reference. The code basically generates a list of packages and converts the list into a JSON collection. This JSON set was later added to the Angularjs. The information for a package in a JSON collection is the initial method that allows the server-side bundle to be loaded from the client Angularjs application.


_layout.cshtml
@using CodeProject.Portal.Models
@{
string version = typeof (CodeProject.Portal.MvcApplication). Assembly.getname (). Version.tostring ();
String baseurl = system.configuration.configurationmanager.appsettings["BaseURL"]. ToString ();

list<custombundle> bundles = new list<custombundle> ();
CodeProject.Portal.Models.CustomBundle Custombundle;

list<string> codeprojectbundles = new list<string> ();
Codeprojectbundles.add ("Home");
Codeprojectbundles.add ("Customers");
Codeprojectbundles.add ("Products");

foreach (String controller in Codeprojectbundles)
{
Custombundle = new CodeProject.Portal.Models.CustomBundle ();
Custombundle.bundlename = Controller;
Custombundle.path = BundleTable.Bundles.ResolveBundleUrl ("~/bundles/" + Controller);
custombundle.isloaded = false;
Bundles. ADD (Custombundle);
}

Bundleinformation bundleinformation = new Bundleinformation ();
Bundleinformation.bundles = bundles;
String Bundleinformationjson = Newtonsoft.Json.JsonConvert.SerializeObject (
Bundleinformation, Newtonsoft.Json.Formatting.None);

}

The asp.net bundle has a lot of functionality. For example, if you want to iterate through all the files, you can execute the Enumeratefiles method and return the virtual path of each file within a particular package.

foreach (var file in bundle.) Enumeratefiles (New Bundlecontext (
New Httpcontextwrapper (HttpContext.Current), Bundletable.bundles, "~/bundles/shared"))
{
String filePath = file. Includedvirtualpath.tostring ();
}
_layout.cshtml-Title
In the title section of the HTML document, there is a requirejs reference. The application uses the REQUIREJS dynamic load package through the client Angularjs code. Requirejs is an asynchronous module definition (AMD) loaded with JavaScript API modules. Requirejs has many features, but for instance applications, only request features from REQUIREJS are required for use in later applications.

In addition, the Scripts.render and Styles.render methods will be executed in the beginning section. When an application executes in debug mode or when Enableoptimizations is accused of false, the rendered method will generate multiple scripts in each bundle. When in publish mode and when optimization is enabled, the rendering method generates a script tag to represent the entire bundle's version stamp.

This leads to another challenge, that is, the application needs to support the ability to generate bundled script tags in release mode, and the ability to generate script tags for unique files in debug mode. This is important if you want to set breakpoints for JavaScript code in debug mode. Because it is not possible to use the optimized bundle version of JavaScript code in release mode.

Finally, in the title section, the basic URL using the Razor syntax is set early as the base URL variable on the server side.


<!--_layout.cshtml-->

! DOCTYPE html>
<meta charset= "Utf-8"/>
<meta name= "viewport" content= "Width=device-width, initial-scale=1.0" >
<meta http-equiv= "Cache-control" content= "No-cache, No-store, must-revalidate"/>
<meta http-equiv= "Pragma" content= "No-cache"/>
<meta http-equiv= "Expires" content= "0"/>

<title>angularjs MVC Code project</titlev>

<script src= "~/scripts/require.js" ></script>

@Scripts. Render ("~/bundles/jquery")
@Scripts. Render ("~/bundles/bootstrap")
@Scripts. Render ("~/bundles/modernizr")
@Scripts. Render ("~/bundles/angular")

@Styles. Render ("~/content/css")

<base href= "#baseUrl"/>

Debug mode vs Release mode
The @Scripts when Enableoptimizations is set to false or when running in debug mode. The Render method produces a variety of script tags in each bundle. This is necessary if you want to set breakpoints and debug JavaScript files. You have another option, that is, in debug mode, use the Renderformat method to select the client script tag.

The following code fragment is included in the _layout.cshtml master page, and Renderformat is used when the application is in debug mode. In this mode, the applied version sequence number is appended to the Script tab of all JavaScript files in the bundle. This is a small fix for a standard render script tag format that does not contain an additional version number.

When you start an application from Visual Studio, you may experience a problem with browser caching. It may also take time to guess whether you are running the latest version of JavaScript files. Pressing F5 in the browser can solve this problem. To avoid this problem, the application version number is appended to the script tag. With the automatic version plug-in, the version number is automatically incremented in each build. Using this technique, I was able to know that every compile and run was using the latest version of JavaScript files, which saved me a lot of time.


//_layout.cshtml
@if (HttpContext.Current.IsDebuggingEnabled)
{
    @ Scripts.renderformat ("<script type=\" text/javascript\ "src=\" {0}?ver = "+ @version +" \ "
                             </script>, "~/bundles/shared")
    @Scripts. Renderformat ( "<script type=\" text/javascript\ "src=\" {0}?ver = "+ @version +" \ "
      & nbsp;                     </script> "~/bundles/routing-debug")
}
Else
{
    @Scripts. Render ("~/bundles/shared")
    @Scripts. Render ("~/bundles/routing-production")
}

Bridge between server-side Razor data and Angularjs
Now that I've created a collection of server-side bundled data, the next challenge is to inject and create a bridge between server-side and client-Angularjs code. On the _layout.cshtml master page, I created an anonymous JavaScript feature that could create a angularjs vendor. Initially I planned to create a regular ANGULARJS service or a set of methods that could be injected into the server by using the Razor syntax in a _layout.cshtml file.

Unfortunately, the Angularjs service and method set will not be available until the ANGULARJS configuration phase is complete, so I cannot create a service with no angularjs errors in the home page. To overcome this limitation, you need to create a ANGULARJS provider. The function of a provider is to be able to create an instance that provides a set of methods and services. The provider allows you to create and configure a service during the angular configuration process.

The service provider name starts with the provider for the work they provide. In the following code snippet, the code creates a "ApplicationConfiguration" provider that is being referenced by Applicationconfigurationprovider. This provider will be configured in the constructor to set the assembly version number and bundle list required for the application for the dynamic request. The MVC Razor code injects server-side data into the constructor.


//_layout.cshtml
(function () {
        var codeprojectapplication = Angular.module (' CodeProject ');
        codeprojectapplication.provider (' ApplicationConfiguration ', function () {
            var _version;
             var _bundles;
            return {
                 setversion:function (version) {
                 _version = version;
           },

Setbundles:function (Bundles) {
_bundles = bundles;
},

Getversion:function () {
return _version;
},

Getbundles:function () {
return _bundles;
},

            $get: function () {
                 return {
                     version: _version,
                     bundles: _bundles
                }
           }
       }
   });

Codeprojectapplication.config (function (applicationconfigurationprovider) {
Applicationconfigurationprovider.setversion (' @version ');
Applicationconfigurationprovider.setbundles (' @Html. Raw (Bundleinformationjson) ');
});
})();

Routing generation and dynamic loading MVC bundles
Now you may have seen many examples of angularjs examples that implement a hard-coded path for each content page. The example application route uses a convention based approach, which allows the routing table to use a hard-coded routing method to implement a rule-based approach. All content pages and associated JavaScript files follow the naming convention rule, which allows the application to resolve routing and dynamically determine which JavaScript files are required for each content page.

The following sample application's routing table only needs to parse out three routes:

One for the root path '/'
A standard routing path, such as '/:section/:tree '
A route that contains routing parameters, such as '/:section/:tree/:id '
I decided to load the JavaScript file from the asp.net bundle, and the following routing configuration code needed to contain some applicationconfigurationprovider references to create the bundle information before the save. Bundle information will be parsed into a JSON set. The bundle information set will be used to return the virtual bundle path. In addition, the JSON set will be used to track bundled bundles that are loaded. Once the bundle is loaded, there is no need to bundle it for a second time.

There are a few things that need to be written into the routing code. First, all JavaScript files that are bound to a module need to be downloaded whenever a user chooses a page to load a certain function module. For example, when a user selects a content page in customer mode, the following code looks at whether the bundle of the module has been checked through the IsLoaded property of the JSON _bundles collection, and if isLoaded is false, the bundle will be recorded. The IsLoaded property is set to true.

When determining which pattern bundles to download, there are two things to load bundles: Deferred promise and Requirejs. Deferred promise can help you run the function asynchronously, and when it completes execution, it returns.

Now, the last piece of the puzzle is to determine how to load from the client code package. In my previous article codeproject.com used Requirejs (mentioned above) to dynamically load JavaScript files, I used bundles to load REQUIREJS. Using the Requirejs "Requirements" feature, I enter the requirements function through bundled virtual paths. As it turns out, the requirements feature will load any path that is better able to perform a bundled load.

When I first used the Requirejs path to download the bundle, I had finished Requirejs and all of its configurations. It turns out that I was able to get rid of all of this, simply loading the Requirejs library and using its requirements functionality. I didn't even use the REQUIREJS definition representation to preinstall my dynamic load controller. After many experiments and errors, I have reached the purpose of this article. I can now load server-side bundles through client code.


//Codeprojectrouting-production.js
Angular.module ("CodeProject"). config (
[' $routeProvider ', ' $ Locationprovider ', ' applicationconfigurationprovider '
    function ($routeProvider, $ Locationprovider, Applicationconfigurationprovider) {
        var Basesiteurlpath = $ ("base"). A (). attr ("href");
        var _bundles = Json.parse ( Applicationconfigurationprovider.getbundles ());
        this.getapplicationversion = function () {
             var applicationversion = Applicationconfigurationprovider.getversion ();
            return applicationversion;
       }
        this.getbundle = function (bundlename) {

for (var i = 0; i < _bundles. Bundles.length; i++) {
if (bundlename.tolowercase () = = _bundles. Bundles[i]. Bundlename) {
Return _bundles. Bundles[i]. Path;
}
}
}
this.isloaded = function (bundlename) {
for (var i = 0; i < _bundles. Bundles.length; i++) {
if (bundlename.tolowercase () = = _bundles. Bundles[i]. Bundlename) {
Return _bundles. Bundles[i]. IsLoaded;
}
}
}
this.setisloaded = function (bundlename) {
for (var i = 0; i < _bundles.length; i++) {
if (bundlename.tolowercase () = = _bundles. Bundles[i]. Bundlename) {
_bundles. Bundles[i]. IsLoaded = true;
Break
}
}
}
$routeProvider. When ('/:section/:tree '),
{
Templateurl:function (RP) {return basesiteurlpath + ' views/' +
Rp.section + '/' + Rp.tree + '. html?v= ' + this.getapplicationversion (); },
Resolve: {
Load: [' $q ', ' $rootScope ', ' $location ', function ($q, $rootScope, $location) {
var path = $location. Path (). Split ("/");
var parentpath = path[1];
var bundle = This.getbundle (Parentpath);
var isbundleloaded = this.isloaded (Parentpath);
if (isbundleloaded = = False) {
This.setisloaded (Parentpath);
var deferred = $q. Defer ();
require ([bundle], function () {
$rootScope. $apply (function () {
Deferred.resolve ();
});
});
return deferred.promise;
}
}]
}
});
$routeProvider. When ('/:section/:tree/:id '),
{
Templateurl:function (RP) {return basesiteurlpath + ' views/' +
Rp.section + '/' + Rp.tree + '. html?v= ' + this.getapplicationversion (); },
Resolve: {
Load: [' $q ', ' $rootScope ', ' $location ', function ($q, $rootScope, $location) {
var path = $location. Path (). Split ("/");
var parentpath = path[1];
var bundle = This.getbundle (Parentpath);
var isbundleloaded = this.isloaded (Parentpath);
if (isbundleloaded = = False) {
This.setisloaded (Parentpath);
var deferred = $q. Defer ();
require ([bundle], function () {
$rootScope. $apply (function () {
Deferred.resolve ();
});
});
return deferred.promise;
}
}]
}
});
$routeProvider. When ('/',
{
Templateurl:function (RP) {
return Basesiteurlpath + ' views/home/index.html?v= ' + this.getapplicationversion (); },
Resolve: {
Load: [' $q ', ' $rootScope ', ' $location ', function ($q, $rootScope, $location) {
var bundle = This.getbundle ("Home");
var isbundleloaded = this.isloaded ("Home");
if (isbundleloaded = = False) {
this.setisloaded ("Home");
var deferred = $q. Defer ();
require ([bundle], function () {
$rootScope. $apply (function () {
Deferred.resolve ();
});
});
return deferred.promise;
}
}]
}
});
$locationProvider. Html5mode (True);
}
]);


Debug routing Table-HTML cache cleanup
Just after I thought the sample application was complete, I realized that I had to provide two versions of the routing table: one running in debug mode and one running in publishing mode. In debug mode, JavaScript files are downloaded without using the compression feature. This is necessary if you want to debug and set breakpoints in the JavaScript controller. In fact, there are some challenges with the generation of routing tables, because the routing code is using JavaScript bundles, but under Visual Studio, the bundle cannot be debugged step-by-step, so I can't debug the code. I had to develop and test some console.log commands along with some JavaScript statement alerts to generate the routing table.

All two routing versions contain a cache of HTML files, like bundles and JavaScript, and you also need to provide a serial number attached to the HTML angular view. In both debugging and generation of routing code, the embedded version number is rolled out of the applicationconfigurationprovder and attached to the cached HTML path.


Codeprojectrouting-debug.js

Angular.module ("CodeProject"). config (
[' $routeProvider ', ' $locationProvider ', ' Applicationconfigurationprovider ',

function ($routeProvider, $locationProvider, Applicationconfigurationprovider) {

This.getapplicationversion = function () {
var applicationversion = applicationconfigurationprovider.getversion ();
return applicationversion;
}

var Basesiteurlpath = $ ("base").---------attr ("href");

$routeProvider. When ('/:section/:tree '),
{
Templateurl:function (RP) {return basesiteurlpath + ' views/' +
Rp.section + '/' + Rp.tree + '. html?v= ' + this.getapplicationversion (); },

Resolve: {

Load: [' $q ', ' $rootScope ', ' $location ', function ($q, $rootScope, $location) {

var path = $location. Path (). Split ("/");
var directory = path[1];
var controllername = path[2];

var controllertoload = "views/" + Directory + "/" +
Controllername + "controller.js?v=" + this.getapplicationversion ();

var deferred = $q. Defer ();

Require ([Controllertoload], function () {
$rootScope. $apply (function () {
Deferred.resolve ();
});
});

return deferred.promise;

}]
}

});

$routeProvider. When ('/:section/:tree/:id '),
{
Templateurl:function (RP) {return basesiteurlpath + ' views/' +
Rp.section + '/' + Rp.tree + '. html?v= ' + this.getapplicationversion (); },

Resolve: {

Load: [' $q ', ' $rootScope ', ' $location ', function ($q, $rootScope, $location) {

var path = $location. Path (). Split ("/");
var directory = path[1];
var controllername = path[2];

var controllertoload = "views/" + Directory + "/" + Controllername +
"controller.js?v=" + this.getapplicationversion ();

var deferred = $q. Defer ();

Require ([Controllertoload], function () {
$rootScope. $apply (function () {
Deferred.resolve ();
});
});

return deferred.promise;

}]
}

});

$routeProvider. When ('/',
{

Templateurl:function (RP) {return basesiteurlpath + ' views/home/index.html?v= ' +
This.getapplicationversion (); },

Resolve: {

Load: [' $q ', ' $rootScope ', ' $location ', function ($q, $rootScope, $location) {

var controllertoload = "views/home/indexcontroller.js?v=" +
This.getapplicationversion ();

var deferred = $q. Defer ();

Require ([Controllertoload], function () {
$rootScope. $apply (function () {
Deferred.resolve ();
});
});

return deferred.promise;

}]
}

});

$locationProvider. Html5mode (True);

}]);


Test browser cache
When developing a WEB application, one of the things you want to do is to test all browser caching and caching cleanup capabilities. You will want to make sure that your application is downloaded and cached correctly, and that the content will appear after the page request.

You will make a lot of changes to your content to rebuild your application to make sure that the problem of cleaning up the cache and downloading the newer version of the content is resolved.

To test all this, I run the app in release mode through the Chrome browser and click F12 to open the Network tab. Here, you can see how much time it takes to download your application and the content from the server, or the browser's cache. You can even see the bundle download.

Eventually, you click on all the pages of your application and you'll find that all the content is coming from the browser cache, which is the beauty of a single page application. All of your content will end up with a larger cache response time, and the only thing to do is to click the Web server to return the JSON-formatted data from the RESTful Web API presented in the page.

Other interesting points
Interesting points in other instance applications, as well as execution of. NET libraries on the server side. For data validation input, the application uses the Fluentvalidation library in the business process.

Fluentvalidation is a small validation library of. NET that uses fluent interfaces and lambda expressions to establish validation rules.

The customer code and company name are required when attempting to create a customer for the sample application. The business layer Management effectiveness of the sample application uses the Fluentvalidation library validation. By passing a dense client object into the CreateCustomer method, the properties on the object can be validated by the business rules of the set fluentvalidation expression. If the business object validation fails, the business layer can return the wrong collection from the validation library and send the error collection results to the client for rendering the browser-side error message.


Public Customer CreateCustomer (customer customer, out transactionalinformation transaction)
{
Transaction = new Transactionalinformation ();

Try
{
Customerbusinessrules customerbusinessrules = new Customerbusinessrules ();
Validationresult results = customerbusinessrules.validate (customer);

BOOL validationsucceeded = results. IsValid;
ilist<validationfailure> failures = results. Errors;

if (validationsucceeded = = False)
{
Transaction = validationerrors.populatevalidationerrors (failures);
return customer;
}

_customerdataservice.createsession ();
_customerdataservice.begintransaction ();
_customerdataservice.createcustomer (customer);
_customerdataservice.committransaction (TRUE);

Transaction. ReturnStatus = true;
Transaction. Returnmessage.add ("Customer successfully created.");

}
catch (Exception ex)
{
String errormessage = ex. message;
Transaction. Returnmessage.add (errormessage);
Transaction. ReturnStatus = false;
}
Finally
{
_customerdataservice.closesession ();
}

return customer;
}

The following is a business rule class that defines a customer object, uses the Fluentvalidation library, defines a set of lambda expressions, and creates business rules and each validation-related error message. The Fluentvalidation library uses a different set of lambda expressions to validate business objects or entities.


Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Text;
Using System.Threading.Tasks;
Using Fluentvalidation;
Using CodeProject.Business.Entities;
Using System.Configuration;
Using Codeproject.interfaces;

Namespace Codeproject.business
{
public class Customerbusinessrules:abstractvalidator<customer>
{

Public Customerbusinessrules ()
{
Rulefor (c => c.companyname). Notempty (). Withmessage ("Company Name is required.");
Rulefor (c => c.customercode). Notempty (). Withmessage ("Customer Code is required.");
}

}

}

Another notable point in the sample application is the implementation of dependency injection using the Ninject library. When Ninject is installed from NuGet, a configuration file NinjectWebCommon.cs will be created for you. Here, you can tell the Ninject library what objects to create when certain parts of the application are executed, such as in the Web API service. In the following registerservices, I told Ninject to assign customer Data services and product data services to the interfaces they implemented. That tells Ninject where to go. Loads a matching DLL reference.


Namespace CodeProject.Portal.App_Start
{
Using System;
Using System.Web;

Using Microsoft.Web.Infrastructure.DynamicModuleHelper;

Using Ninject;
Using Ninject.Web.Common;

public static Class Ninjectwebcommon
{
private static readonly Bootstrapper Bootstrapper = new Bootstrapper ();

<summary>
Starts the application
</summary>
public static void Start ()
{
Dynamicmoduleutility.registermodule (typeof (Oneperrequesthttpmodule));
Dynamicmoduleutility.registermodule (typeof (Ninjecthttpmodule));
Bootstrapper. Initialize (Createkernel);
}

<summary>
Stops the application.
</summary>
public static void Stop ()
{
Bootstrapper. ShutDown ();
}

<summary>
Creates the kernel that would manage your application.
</summary>
<returns>the created Kernel.</returns>
private static Ikernel Createkernel ()
{
var kernel = new Standardkernel ();
Try
{
Kernel. Bind<func<ikernel>> (). Tomethod (CTX => () => new Bootstrapper (). Kernel);
Kernel. Bind<ihttpmodule> (). To

Registerservices (kernel);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver =
New Ninject.Web.WebApi.NinjectDependencyResolver (kernel);
return kernel;
}
Catch
{
Kernel. Dispose ();
Throw
}
}

<summary>
Load your modules or register your services here!
</summary>
<param name= "kernel" >the kernel.</param>
private static void Registerservices (Ikernel kernel)
{
Kernel. Bind<codeproject.interfaces.icustomerdataservice> ().
To<codeproject.data.entityframework.customerdataservice> ();
Kernel. Bind<codeproject.interfaces.iproductdataservice> ().
To<codeproject.data.entityframework.productdataservice> ();

}
}
}

Using Ninject data annotation [injection], you can tell Ninject when and where to instantiate your object. In the Web API service below, customer data services are created by Ninject. Because customer business services rely on the services of customer data to access data, customer data services should be injected into the constructor of the customer's business services. All of this is done by creating a service interface for customer data and then simply implementing the Customer data service interface. Dependency injection is powerful because it creates a low coupling application layer that uses code to separate from each other.


Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Net;
Using System.Net.Http;
Using System.Web.Http;
Using CodeProject.Portal.Models;
Using CodeProject.Business.Entities;
Using Codeproject.business;
Using Codeproject.interfaces;
Using Ninject;

Namespace CodeProject.Portal.WebApiControllers
{
[Routeprefix ("Api/customerservice")]
public class Customerservicecontroller:apicontroller
{

[Inject]
Public Icustomerdataservice _customerdataservice {get; set;}

<summary>
Create Customer
</summary>
<param name= "Request" ></param>
<param name= "Customerviewmodel" ></param>
<returns></returns>
[Route ("CreateCustomer")]
[HttpPost]
Public Httpresponsemessage CreateCustomer (httprequestmessage request,
[Frombody] Customerviewmodel Customerviewmodel)
{
Transactionalinformation transaction;

Customer customer = new Customer ();
Customer.companyname = Customerviewmodel.companyname;
Customer. ContactName = Customerviewmodel.contactname;
Customer. ContactTitle = Customerviewmodel.contacttitle;
Customer. Customercode = Customerviewmodel.customercode;
Customer. address = customerviewmodel.address;
Customer. City = customerviewmodel.city;
Customer. Region = customerviewmodel.region;
Customer. PostalCode = Customerviewmodel.postalcode;
Customer. Country = Customerviewmodel.country;
Customer. PhoneNumber = Customerviewmodel.phonenumber;
Customer. Mobilenumber = Customerviewmodel.mobilenumber;

Customerbusinessservice Customerbusinessservice =
New Customerbusinessservice (_customerdataservice);

            Customerbusinessservice.createcustomer ( Customer, out transaction);
            if (transaction. ReturnStatus = = False)
            {                
                 customerviewmodel.returnstatus = false;
                Customerviewmodel.returnmessage = transaction. ReturnMessage;
                Customerviewmodel.validationerrors = transaction. validationerrors;

                var responseerror = Request.createresponse<customerviewmodel>
                                      (Httpstatuscode.badrequest, Customerviewmodel);
                return Responseerror;
             
            }

Customerviewmodel.customerid = customer. CustomerID;
Customerviewmodel.returnstatus = true;
Customerviewmodel.returnmessage = transaction. ReturnMessage;

var response = request.createresponse<customerviewmodel>
(Httpstatuscode.ok, Customerviewmodel);
return response;

}

Conclusion
Integrating Angularjs in asp.net MVC and asp.net bundles seems to be an attempt to start looking like a challenge. In every iteration of experimentation and failure, the challenge becomes progressively less difficult. I just want to make all this work together and I won't stop trying.

You can argue about the advantages of using bundled and indented functions in asp.net and using popular compression tools in the grunt and Gulp sections. If you're a Microsoft developer who doesn't need to learn additional technology and tools and likes to click on a button to publish your Visual Studio, you'll probably want to use the ASP.net bundle feature. I found that this feature was really what I wanted and it just took me a long time to figure out how to integrate it with ANGULARJS.

In these days, there are many techniques to write. Some of my future articles may include the rest of Angularjs 2 and MEAN, including Node.js, Express and MongoDB.

There are also some mobile applications developed using Apache Cordov that are included in the latest release of Visual Studio 2015. This advanced HTML Hybrid mobile application framework is likely to work with Apache Cordov. It is said that ionic can use HTML and Angularjs, and can easily build large-scale interactive mobile applications. Please look forward to it!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.