购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session

简介: 原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session  chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解。
原文: 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session

 

chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解。


文章:
http://chsakell.com/2015/01/31/angularjs-feat-web-api/
http://chsakell.com/2015/03/07/angularjs-feat-web-api-enable-session-state/

 

源码:
https://github.com/chsakell/webapiangularjssecurity

 

本系列共三篇,本篇是第二篇。


购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端
购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session
购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证

 

HomeController用来展示主页面,并接受前端传来的Order的编号。

 

public calss HomeCOntroller : Controller
{
    public ActionReuslt Index()
    {
        retun View();
    }
    
    public ActionResult ViewOrder(int id)
    {
        using(var context = new SotreContext())
        {
            //这时候Order的导航属性Gadgets还没有加载出来呢
            var order = context.Orders.Find(id);
            
            //根据Order编号获取中间表
            var gadgetOrders = context.GadgetOrders.Where(go => go.OrderID == id);
            
            foreach(GadgetOrder gadgetOrder in gadgetOrders)
            {
                //加载中间表某个记录中对应的导航属性
                context.Entry(gadgetOrder).Reference(g => g.Gadget).Load();
                order.Gadgets.Add(gadgetOrder.Gadget);
            }
            return View(order);
        }
    }
}

 

Home/Index.cshtml视图。

 

<html ng-app="gadgetsStore">
    ...
    <body ng-controller='gadgetStoreCtrl'>
        <div ng-hide="checkoutComplete()">
            <div ng-show="showFilter()">
                <form>
                    <input type="text" ng-model="searchItem">
                </form>
            </div>
            <cart-details></cart-details>
        </div>
        <div ng-show="data.error" ng-cloak>
            {{data.error.status}}
        </div>
        <ng-view />
        
        <script src="../../Scripts/angular.js" type="text/javascript"></script>
        <script src="../../Scripts/angular-route.js" type="text/javascript"></script>
        
        <script src="../../app/mainApp.js"></script>
        <script src="../../app/controllers/gadgetsStore.js" type="text/javascript"></script>
        <script src="../../app/filters/storeFilters.js" type="text/javascript"></script>
        <script src="../../app/controllers/gadgetsControllers.js" type="text/javascript"></script>
        <script src="../../app/components/cartCmp.js" type="text/javascript"></script>
        <script src="../../app/controllers/checkoutController.js" type="text/javascript"></
    </body>
</html>

 

以上,ng-hide="checkoutComplete()"决定着是否显示所在div,ng-show="data.error" 决定是否显示报错,<ng-view />根据路由显示不同视图,ng-cloak用来避免在切换视图时页面的闪烁,<cart-details></cart-details>是自定义的directive,和angularjs有关的js文件放在顶部,applicaiton相关js文件放在其下面,在mainApp.js文件中坐落着一个顶级module名称是gadgetStore,而顶级controller被放在了gadgetsStoreCtrl.js这个js文件中了。


最终的界面如下:

 

main.js 声明顶级module,以及配置路由。

 

angular.module("gadgetsStore", ["storeFilters", "storeCart", "ngRoute"])
    .config(function($routeProvider){
        $routeProvider.when("/gadgets",{templateUrl: "app/views/gadgets.html"});
        $routeProvider.when("/checkout",{templateUrl: "app/views/checkout.html"});
        $routeProvider.when("/submitorder",{templateUrl: "app/views/submitOrder.html"});
        $routeProvider.when("/complete",{templateUrl: "app/views/orderSubmitted.html"});
        $routeProvider.otherwise({templateUrl: "app/views/gadgets.html"});
    });

 

storeFilters, storeCart是我们自定义的,这里注入进来。

 

有了gadgetsStore这个module,现在就为这个module添加controller等。

 

angular.module('gadgetsStore')
    .constant('gadgetsUrl', 'http://localhost:8888/api/gadgets')
    .constant('ordersUrl', 'http://localhost:8888/api/orders')
    .constant('categoreisUrl', 'http://localhost:8888/api/categories')
    .controller('gadgetStore', function($scope, $http, $location, gadgetsUrl, categoresUrl, ordersUrl, cart){//因为gadgetsStore依赖引用了storeCart,所以这里可以引用cart
    
        //这里的data被用在主视图上,所以data的数据会被其它部分视图共享
        // $scope.data.gadgets
        // scope.data.erro
        // $scope.data.categories
        // $scope.data.OrderLocation
        // $scope.data.OrderID
        // $scope.data.orderError
        $scope.data = {};
        
        $http.get(gadgetsUrl)
            .success(function(data){
                $scope.data.gadgets = data;
            })
            .error(function(error){
                $scope.data.error = error;
            });
            
        $http.get(categoresUrl)
            .success(function(data){
                $scope.data.categories = data;
            })
            .error(function(error){
                $scope.data.error = error;
            });
            
        $scope.sendOrder = function(shippingDetails){
            var order = angular.copy(shippingDetails);
            order.gadgets = cart.getProducts();
            $http.post(ordersUrl, order)
                .success(function(data, status, headers, config){
                    $scope.data.OrderLocation = headers('Location');
                    $scope.data.OrderID = data.OrderID;
                    cart.getProducts().length = 0;
                })
                .error(function(error){
                    $scope.data.orderError = error;
                }).finally(function(){
                    $location.path("/complete");
                });
        }
        
        $scope.showFilter = function(){
            return $location.path() == '';
        }
        
        $scope.checkoutComplete = function(){
            return $location.path() == '/complete';
        }
    });

 

以上,为gadgetsStore这个module定义了常量以及controller。把一些规定的uri定义成某个moudule的常量是很好的习惯。通过$location.path方法可以获取或设置当前窗口的uri。

 

好了,顶级的module和顶级的controller有了,Gadget部分如何显示呢?

 

根据路由$routeProvider.when("/gadgets",{templateUrl: "app/views/gadgets.html"}), Gadget的视图被放在了app/views/gadgets.html中了,来看gadgets.html这个视图。

 

<div ng-controller="gadgetsCtrl" ng-hide="data.error">

    <!--左侧导航部分-->
    <div>
        <!--这里的selectCategory方法实际是把controller内部的一个变量selectedCategory设为null-->
        <a ng-click="selectCategory()">Home</a>
        <a ng-repeat="item in data.categoires | orderBy: 'CategoryID'" ng-click="selectCategory(item.CategoryID)" ng-class="getCategoryClass(item.CategoryID)">{{item.Name}}</a>
    </div>
    
    <!--右侧Gadgets部分-->
    <div>
        <div ng-repeat="item in data.gadgets | filter: categoryFilterFn | filter: searchItem | range:selectedPage:pageSize">
            {{item.Name}}
            {{item.Price | currency}}
            <img ng-src="../../images/{{item.Images}}" />
            {{item.Description}}
            
            <a ng-click="addProductToCart(item)">Add To Cart</a>
        </div>
        
        <!--分页部分-->
        <div>
            <a ng-repeat="page in data.gadgets | filter:categoryFilterFn | filter:searchItem | pageCount:pageSize" ng-click="selectPage($index + 1)" ng-class="getPageClass($index + 1)">
                {{$index + 1}}
            </a>
        </div>
    </div>
</div>

 


以上,把视图的来源交给了gadgetsCtrl这个controller, 这个controller也被定义在了gadgetsStore这个module中。

 

gadgetsCtr.js

 

angular.module("gadgetsStore")
    .constant("gadgetsActiveClass", 'btn-primary')
    .constant('gadgetsPageCount', 3)
    .controller("gadgetsCtrl", function($scope, $filter, gadgetsActiveClass, gadgetsPageCount, cart){
    
        //存储Category的主键CategoryID
        var selectedCategory = null;
        
        //这里是传给range和pageCount过滤器的
        $scope.selectedPage = 1;
        $scope.pageSise = gadgetsPageCount;
        
        //实际就是未selectedPage这个变量赋新值
        $scope.selectPage = function(newPage){
            $scope.selectedPage = newPage;
        }
        
        //这里把Category的编号CategoryID传了进来
        $scope.selecteCategory = function(newCategory)
        {
            $selectedCategory = newCategory;
            $scope.selectedPage = 1; 
        }
        
        //这里的product实际就是Gadget
        //过滤出Gadget的CategoryID和这里的selectedCateogory一致的那些Gadgets
        $scope.categoryFilterFn = fucntion(product){
            return selectedCategory == null || product.CategoryID == selectedCategory;
        }
        
        //category实际是Category的主键CategoryID
        $scope.getCategoryClass = function(category){
            return selectedCategory == category ? gadgetsActiveClass : "";
        }
        
        $scope.getPageClass = function(page){
            return $scope.selectedPage = page ? gadgetsActiveClass : "";
        }
        
        $scope.addProductToCart = function(product){
            cart.addProduct(product.GadgetID, product.Name, product.Price, product.CategoryID);
        }
    });

 

在显示Gadget列表的时候,<div ng-repeat="item in data.gadgets | filter: categoryFilterFn | filter: searchItem | range:selectedPage:pageSize">,这里用到了一个自定的过滤器range,这个过滤器被定义在了storeFilters.js中。

 

var storeFilters = angular.module('storeFilters',[]);

storeFitlers.filter("range", function($filter){
    return function(data, page, size){
        if(angular.isArray(data) && angular.isNumber(page) && angular.isNumber(size)){
            var start_index = (page - 1)*size;
            if(data.legnth < start_index){
                return [];
            } else {
                return $filter("limitTo")(data.splice(start_index), size);
            }
        } else{
            return data;
        }
    }
});

sortFilters.filter("pageCount", function(){
    return function(data, size){
        if(angular.isArray(data))
        {
            var result = [];
            for(var i = 0; i < Math.ceil(data.length/size); i++){
                result.push(i);
            }
        } else {
            return data;
        }
    }
});

 

再来看$routeProvider.when("/checkout",{templateUrl: "app/views/checkout.html"});这个路由,checkout.html这个部分视图如下:

 

<div ng-controller = "cartDetailsController">
    <div ng-show="cartData.length==0">
        no item in the shopping cart
    </div>
    <div ng-hide="cartData.length == 0">
        {{item.count}}
        {{item.Name}}
        {{item.Price | currency}}
        {{(item.Price * item.count) | currency}}
        <button ng-click="remove(item.GadgetID)"></button>
        {{total() | currency}}
        <a href="#">Continue shopping</a>
        <a href="#/submitorder">Place order now</a>
    </div> 
</div>

 

对应的界面如下:

 

 

cartDetailsController这个controller也被放在了顶级module里。如下:

 

 

angular.module("gadgetsStore")
    .controller("cartDetailsController", function($scope, cart){
        $scope.cartData = cart.getProducts();
        
        $scope.total = function(){
            var total  = 0;
            for(var i = 0; i < $scope.cartData.length;i++)
            {
                total += ($scope.cartData[i].Price * $scope.cartData[i].count);
            }
            return total;
        }
        
        $scope.remove = function(id){
            cart.removeProduct(id);
        }
    });

 

我们注意到,我们已经在多个地方注入cart这个服务 ,这个自定义的服务可以以factory的方式来创建,如果要用这个cart服务,它所在的module就要被其它module所引用。下面来创建cart服务:

 

var storeCart = angular.module('storeCart',[]);

storeCart.factory('cart', function(){
    var cartData = [];
    
    return {
        addProduct: function(id, name, price, category){
        
            //用来标记是否已经向购物车里加了产品
            var addedToExistingItem = false;
            for(var i=0; i < cartData.length;i++)
            {
                if(cartData[i].GadgetID == id){
                    cartData[i].count++;
                    addedToExistingItem = true;
                    break;
                }
            }
            if(!addedToExistingItem)
            {
                cartData.push({
                    count:1, GadgetID: id, Price: price, Name: name, CategoryID:category
                });
            }
        },
        removeProduct: function(id){
            for(var i = 0; i < cartData.legnth; i++){
                if(cartData[i].GadgetID == id){
                    cartData.splice(i, 1);
                    break;
                }
            }
        },
        getProducts:function(){
            return cartData;
        }
    
    };
});

 

关于购物车部分,我们还记得,在主视图用了<cart-details></cart-details>这个自定义的directive,实际也是在storeCart这个module中定义的。

 

sortCart.directive("cartDetails", function(cart){
    return {
        restrict: "E",
        templateUrl: "app/components.cartDetails.html",
        controller: function($scope){
            var cartData = cart.getProducts();
            
            $scope.total = function(){
                var total =0;
                for(var i = 0; i < cartData.legnth; i++){
                    total += (cartData[i].Price * cartData[i].count);
                }
                return total;
            }
            
            $scope.itemCount = function(){
                var total = 0;
                for(var i = 0; i < cartData.length; i++){
                    total += cartData[i].count;
                }
                return total;
            }
        }
    };
});

 

以上,对应的视图为:

 

Your cart: {{itemCount()}} items
{total() | currency}
<a href="#/checkout">Checkout</a>

 

在显示购物车明细的时候,给出了提交订单的链接:

<a href="#/submitorder">Place order now</a>

 

根据路由$routeProvider.when("/submitorder",{templateUrl: "app/views/submitOrder.html"}),是会加载app/views/submitOrder.html部分视图,界面如下:

 

 

对应的html为:

 

<form name="shippingForm" novalidate>
    <input name="companyName" ng-model="data.shipping.CompanyName" required />
    <span ng-show="shippingForm.companyName.$error.required"></span>
    
    <input name="name" ng-model="data.shipping.OwnerName" required />
    <span ng-show="shippingorm.name.$error.required"></span>
    
    ...
    <button ng-disabled="shippingForm.$invalid" ng-click="sendOrder(data.shipping)">Complete Order</button>
</form>

 

sendOrder被定义在了顶级module中:

 

$scope.sendOrder = function (shippingDetails) {
            var order = angular.copy(shippingDetails);
            order.gadgets = cart.getProducts();
            $http.post(ordersUrl, order)
            .success(function (data, status, headers, config) {
                $scope.data.OrderLocation = headers('Location');
                $scope.data.OrderID = data.OrderID;
                cart.getProducts().length = 0;
            })
            .error(function (error) {
                $scope.data.orderError = error;
            }).finally(function () {
                $location.path("/complete");
            });
        }

 

/complete会路由到$routeProvider.when("/complete",{templateUrl: "app/views/orderSubmitted.html"}), app/views/orderSubmitted.html部分视图如下:

 

 

其html部分为:

 

<div ng-show="data.orderError">
    {{data.orderError.status}}the order could not be placed, <a href="#/submitorder">click here to try again</a>
</div>
<div ng-hide="data.orderError">
    {{data.OrderID}}
    <a href="#">Back to gadgets</a>
    <a href="{{data.OrderLocation}}">View Order</a>
</div>

 

■ 实现购物车的Session

 

现在为止,还存在的问题是:当刷新页面的时候,购物车内的产品就会消失,即还么有Session机制。

 

与ASP.NET Web API路由相关的HttpControllerRouteHandler, HttpControllerHandler, IRequireSessionState。

 

首先一个继承内置的HttpControllerHandler,并实现内置的IRequiresSessionState接口。

 

public class SessionEnabledControllerHandler : HttpControllerHandler, IRequiresSessionState
{
    public SessionEnabledControllerHandler(RouteData routeData)
        : base(routeData)
    { }
}

 

然后实现一个内置HttpControllerRouteHandler的继承类。

 

public class SessionEnabledHttpControllerRouteHandler : HttpControllerRouteHandler
{
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new SessionEnabledControllerHandler(requestContext.RouteData);
    }
}

 

注释掉WebApiConfig.cs中的代码:

 

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        // Moved to RouteConfig.cs to enable Session
        /*
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
         */
    }
}

 

在RouteConfig中配置如下:

 

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        #region Web API Routes

        // Web API Session Enabled Route Configurations
        routes.MapHttpRoute(
            name: "SessionsRoute",
            routeTemplate: "api/sessions/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        ).RouteHandler = new SessionEnabledHttpControllerRouteHandler(); ;

        // Web API Stateless Route Configurations
        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        #endregion

        #region MVC Routes
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
        #endregion
    }
}

 

以上,需要引用System.Web.Http。

 

现在,如果希望ItemsController中使用Session,那就这样请求:

http://localhost:61691/api/sessions/items

 

如果不想用Session,那就这样请求:

http://localhost:61691/api/items

 

现在,在前端,向购物车添加产品相关代码为:

 

addProduct: function (id, name, price, category) {
    var addedToExistingItem = false;
    for (var i = 0; i < cartData.length; i++) {
        if (cartData[i].GadgetID == id) {
            cartData[i].count++;
            addedToExistingItem = true;
            break;
        }
    }
    if (!addedToExistingItem) {
        cartData.push({
            count: 1, GadgetID: id, Price: price, Name: name, CategoryID: category
        });
    }
}

 

类似地,创建一个模型:

 

public class CartItem
{
    public int Count { get; set; }
    public int GadgetID { get; set; }
    public decimal Price { get; set; }
    public string Name { get; set; }
    public int CategoryID { get; set; }
}

 

对应的控制器为:

 

public class TempOrdersController : ApiController
{
    //get api/TempOrders
    public List<CartItem> GetTempOrders()
    {
        List<CartItem> cartItems = null;
        
        if(System.Web.HttpContext.Current.Session["Cart"] != null){
            cartItems = (List<CartItem>)System.Web.HttpContext.Current.Session["Cart"];
        }
        
        return cartItems;
    }
    
    //post api/TempOrders
    [HttpPost]
    public HttpResponseMessage SaveOrder(List<CarItem> cartItems)
    {
        if (!ModelState.IsValid)
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }

        System.Web.HttpContext.Current.Session["Cart"] = cartItems;

        return new HttpResponseMessage(HttpStatusCode.OK);
    }
}

 

再回到前端,首先在gadgetsStore这个顶级module中增加有关缓存API的uri常量。

 

angular.module('gadgetsStore')
    .constant('gadgetsUrl', 'http://localhost:61691/api/gadgets')
    .constant('ordersUrl', 'http://localhost:61691/api/orders')
    .constant('categoriesUrl', 'http://localhost:61691/api/categories')
    .constant('tempOrdersUrl', 'http://localhost:61691/api/sessions/temporders')
    .controller('gadgetStoreCtrl', function ($scope, $http, $location, gadgetsUrl, categoriesUrl, ordersUrl, tempOrdersUrl, cart) {
// Code omitted

 

重新定义cart这个服务:

 

storeCart.factory('cart', function(){
    var cartData = [];
    
    return {
        addProduct: function(id, name, price, category){
            var addedToExistingItem = false;
            for(var i = 0; i < cartData.length; i++){
                if(cartData[i].GadgetID == id){
                    cartData[i].count++;
                    addedToExistingItem = true;
                    break;
                }
            }
            if(!addedToExistingItem){
                cartData.push({
                    count:1, GadgetID: id, Price: price, Name: name, Category: category
                });
            }
        },
        removeProduct: fucntion(id){
            for(var i = 0; i < cartData.length; i++){
                if(cartData[i].GadgetID == id){
                    cartData.splice(i, 1);
                    break;
                }
            }
        },
        getProducts: fucntion(){
            return cartData;
        },
        pushItem: function(item){
            cartData.push({
                count: item.Count, GadgetID:item.GadgetID, Price: Item.Price, Name: item.Name, CategoryID: item.CategoryID
            })
        }
    };
});

 


为了在页面每次刷新的时候保证Session的状态,在主module中添加如下方法:

 

//用来把每次更新保存到后端的Session中
$scope.saveOrder = function () {
    var currentProducts = cart.getProducts();

    $http.post(tempOrdersUrl, currentProducts)
        .success(function (data, status, headers, config) {
        }).error(function (error) {
        }).finally(function () {
        });
}

//用来每次刷新向后端Session要数据
$scope.checkSessionGadgets = function(){
    $http.get(tempOrdersUrl)
        .success(function(data){
            if(data){
                for(var i = 0; i < data.length; i++){
                    var item = data[i];
                    cart.pushItem(item);
                }
            }
        })
        .error(function(error){
            console.log('error checking session: ' + error) ;
        });
}

 

然后checkSessionGadgets这个方法就要被运用到主视图上去,当页面每次加载的时候调用它。

 

<body ng-controller='gadgetStoreCtrl' class="container" ng-init="checkSessionGadgets()">

 

每次向购车添加的时候需要重新更新后端的Session状态。

 

$scope.addProductToCart = function (product) {
    cart.addProduct(product.GadgetID, product.Name, product.Price, product.CategoryID);
    $scope.saveOrder();
}

 

每次从购物车一处的时候需要重新更新后端的Session状态。

 

$scope.remove = function (id) {
    cart.removeProduct(id);
    $scope.saveOrder();
}

 

在用户提交订单的时候,需要一出购物车内的产品,再更新后端的Session状态。

 

$scope.sendOrder = function (shippingDetails) {
    var order = angular.copy(shippingDetails);
    order.gadgets = cart.getProducts();
    $http.post(ordersUrl, order)
    .success(function (data, status, headers, config) {
        $scope.data.OrderLocation = headers('Location');
        $scope.data.OrderID = data.OrderID;
        cart.getProducts().length = 0;
        $scope.saveOrder();
    })
    .error(function (error) {
        $scope.data.orderError = error;
    }).finally(function () {
        $location.path("/complete");
    });
}

 

待续~~

 

目录
相关文章
|
24天前
|
开发框架 前端开发 JavaScript
ASP.NET Web Pages - 教程
ASP.NET Web Pages 是一种用于创建动态网页的开发模式,采用HTML、CSS、JavaScript 和服务器脚本。本教程聚焦于Web Pages,介绍如何使用Razor语法结合服务器端代码与前端技术,以及利用WebMatrix工具进行开发。适合初学者入门ASP.NET。
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
166 3
|
4月前
|
编解码 前端开发 JavaScript
.NET_web前端框架_layui_栅格布局
【8月更文挑战第27天】
52 4
|
26天前
|
开发框架 .NET 程序员
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
Autofac 是一个轻量级的依赖注入框架,专门为 .NET 应用程序量身定做,它就像是你代码中的 "魔法师",用它来管理对象的生命周期,让你的代码更加模块化、易于测试和维护
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
|
24天前
|
开发框架 .NET PHP
ASP.NET Web Pages - 添加 Razor 代码
ASP.NET Web Pages 使用 Razor 标记添加服务器端代码,支持 C# 和 Visual Basic。Razor 语法简洁易学,类似于 ASP 和 PHP。例如,在网页中加入 `@DateTime.Now` 可以实时显示当前时间。
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
109 9
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
3月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
111 3
|
3月前
|
开发框架 前端开发 .NET
VB.NET中如何利用ASP.NET进行Web开发
在VB.NET中利用ASP.NET进行Web开发是一个常见的做法,特别是在需要构建动态、交互式Web应用程序时。ASP.NET是一个由微软开发的开源Web应用程序框架,它允许开发者使用多种编程语言(包括VB.NET)来创建Web应用程序。
70 5
|
4月前
|
人工智能 前端开发 开发工具
NET在企业级应用、Web开发、移动应用、云服务及游戏领域的创新实践
.NET技术自2000年推出以来,在软件开发领域扮演着关键角色。本文从核心优势出发,探讨其统一多语言平台、强大工具集、跨平台能力及丰富生态系统的价值;随后介绍.NET在企业级应用、Web开发、移动应用、云服务及游戏领域的创新实践;最后分析性能优化、容器化、AI集成等方面的挑战与机遇,展望.NET技术的未来发展与潜力。
80 2