[ASP.NET MVC 小牛之路]18 - Web API

来源:http://www.cnblogs.com/wangxiaobingya/archive/2017/01/23/6344162.html
-Advertisement-
Play Games

參考頁面: http://www.yuanjiaocheng.net/webapi/test-webapi.html http://www.yuanjiaocheng.net/webapi/web-api-controller.html http://www.yuanjiaocheng.net/we ...


參考頁面:

http://www.yuanjiaocheng.net/webapi/test-webapi.html

http://www.yuanjiaocheng.net/webapi/web-api-controller.html

http://www.yuanjiaocheng.net/webapi/config-webapi.html

http://www.yuanjiaocheng.net/webapi/web-api-route.html

http://www.yuanjiaocheng.net/webapi/parameter-binding.html

Web API 是ASP.NET平臺新加的一個特性,它可以簡單快速地創建Web服務為HTTP客戶端提供API。Web API 使用的基礎庫是和一般的MVC框架一樣的,但Web API並不是MVC框架的一部分,微軟把Web API相關的類從 System.Web.Mvc 命名空間下提取了出來放在 System.Web.Http 命名空間下。這種理念是把 Web API 作為ASP.NET 平臺的核心之一,以使Web API能使用在其他的Web應用中,或作為一個獨立的服務引擎。本文將先帶大家理解Web API,再教大家在MVC中使用Web API。

本文目錄

理解 REST 和 RESTful Web API

為了更好的理解Web API,先帶大家瞭解一下 REST 和 RESTful Web API。以下內容大多來自維基百科

REST(全名:Representational State Transfer),中文翻譯是表徵狀態轉移(也有叫表述性狀態轉移),Roy Fielding博士在2000年他的博士論文中提出來的一種軟體架構風格。

REST 從資源的角度來觀察整個網路,分佈在各處的資源由URI確定,而客戶端的應用通過URI來獲取資源的表徵。獲得這些表徵致使這些應用程式轉變了其狀態。隨著不斷獲取資源的表徵,客戶端應用不斷地在轉變著其狀態,所謂表徵狀態轉移(Representational State Transfer)。

目前使用Web服務的三種主流的方式是:遠程過程調用(RPC),面向服務架構(SOA)以及表徵性狀態轉移(REST),其中REST模式的Web服務與複雜的SOARPC對比來講顯的更加簡潔,越來越多的web服務開始採用REST風格設計和實現。

需要註意的是,REST是設計風格而不是標準,但REST設計風格常基於使用HTTPURI,和XML以及HTML這些現有的廣泛流行的協議和標準。REST設計風格有如下要點:

  • 資源是由URI來指定。
  • 對資源的操作包括獲取、創建、修改和刪除資源,這些操作正好對應HTTP協議提供的GET、POST、PUT和DELETE方法。
  • 通過操作資源的表現形式來操作資源。
  • 資源的表現形式則是XML或HTML,取決於讀者是機器還是人,是消費web服務的客戶軟體還是web瀏覽器。當然也可以是任何其他的格式,如JSON。

另外,使用REST需要滿足一些要求,如客戶端和伺服器結構、連接協議具有無狀態性、能夠利用Cache機制增進性能等。

RESTful Web API(也稱為RESTful Web服務)是一個使用HTTP並遵循REST原則的Web服務。它從以下請求資源的三個方面進行定義:

  • URI,比如:http://example.com/resources/。
  • Web服務接受與返回的互聯網媒體類型,比如:JSON,XML ,YAML 等。
  • Web服務在該資源上所支持的一系列請求方法(比如:POST,GET,PUT或DELETE)。

本文要講的ASP.NET Web API 就是RESTful Web API的一種。下表列出了在實現 RESTful Web API 時HTTP請求方法的典型用途:

不像基於SOAP的Web服務,RESTful Web服務並沒有“正式”的標準。這是因為REST是一種架構,而SOAP只是一個協議。雖然REST不是一個標準,但在實現RESTful Web服務時可以使用其他各種標準(比如HTTP,URL,XML,PNG等)。

那麼REST和本文要講的ASP.NET API又有什麼關係呢?請繼續往下閱讀。

理解 ASP.NET Web API

ASP.NET Web API(本文簡稱Web API),是基於ASP.NET平臺構建RESTful應用程式的框架。可以說 Web API 就是為在.NET平臺下構建RESTful應用程式而生的,這也是本文要先介紹REST的原因。

Web API基於在 MVC 應用程式中添加的一個特殊的 Controller,這種 Controller 稱為 API Controller,和MVC普通的 Controller 相比它主要有如下兩個不同的特點:

  1. Action 方法返回的是 Model 對象,而不是ActionResult。
  2. 在請求時,Action 方法是基於 HTTP 請求方式來選擇的。

第一個不同點很好理解,第二個不同點可能讀者不太理解,一會看完本文的示例就理解了。

從API Controller的Action方法返回給客戶端的Model對象是經過JSON編碼的。API Controller的設計僅是為了提供傳遞Web數據的服務,因此它不支持View、Layout 和其它HTML呈現相關的特性。Web API 能支持任何有Web 功能的客戶端,但最常用的是為Web應用程式中的Ajax請求提供服務。

正如在 ASP.NET MVC 小牛之路]14 - Unobtrusive Ajax 中演示的,我們也可以通過普通的Controller中創建Action方法來返回JSON格式的數據來支持Ajax,但 API controller 的方式可以使得數據相關的Action和View相關的Action分開,並且使得創建只為數據服務的應用更快更簡單。

一般我們會在下麵這兩種情況下選擇使用API Controler:

  1. 需要大量的返回JSON格式數據的Action方法。
  2. 和HTML無關,只是純粹為數據提供服務。

如果你對上面這些概念還不太理解,沒關係,當你閱讀完本文後再回頭看一下,你會對這些概念理解得更深些。

下麵我會通過例子來解釋Web API是如何工作的,它非常簡單,因為很多東西都和我們之前講過的MVC的東西相同。

創建 Web API 應用程式

作為本文的示例,我們創建一個名為 WebServices 的MVC應用程式,選擇Web API模板。在本文的這個例子中,我們創建一個名為 Reservation 的Model,代碼如下:

namespace WebServices.Models {
    public class Reservation {
        public int ReservationId { get; set; }
        public string ClientName { get; set; }
        public string Location { get; set; }
    }
}

為這個Model創建一個Repository 介面和它的一個簡單的實現。如果你對 Repository 這個詞不太理解,可以閱讀:[ASP.NET MVC 小牛之路]05 - 使用 Ninject 。為了簡單,我們直接在Models文件夾中添加一個名為 IReservationRepository 的介面,代碼如下:

namespace WebServices.Models {
    public interface IReservationRepository {
        IEnumerable<Reservation> GetAll();
        Reservation Get(int id);
        Reservation Add(Reservation item);
        void Remove(int id);
        bool Update(Reservation item);
    }
}

創建一個名為 ReservationRepository 的類,實現 IReservationRepository 介面,代碼如下:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
 
namespace WebServices.Models { 
    public class ReservationRepository : IReservationRepository { 
        private List<Reservation> data = new List<Reservation> { 
            new Reservation {ReservationId = 1,  ClientName = "Adam",  
                Location = "London"}, 
            new Reservation {ReservationId = 2,  ClientName = "Steve",  
                Location = "New York"},new Reservation {ReservationId = 3,  ClientName = "Jacqui",  
                Location = "Paris"}, 
        };

        private static ReservationRepository repo = new ReservationRepository();
        public static IReservationRepository getRepository() {
            return repo;
        }

        public IEnumerable<Reservation> GetAll() {
            return data;
        }

        public Reservation Get(int id) {
            var matches = data.Where(r => r.ReservationId == id);
            return matches.Count() > 0 ? matches.First() : null;
        }

        public Reservation Add(Reservation item) {
            item.ReservationId = data.Count + 1;
            data.Add(item);
            return item;
        }

        public void Remove(int id) {
            Reservation item = Get(id);
            if (item != null) {
                data.Remove(item);
            }
        }

        public bool Update(Reservation item) {
            Reservation storedItem = Get(item.ReservationId);
            if (storedItem != null) {
                storedItem.ClientName = item.ClientName;
                storedItem.Location = item.Location;
                return true;
            } else {
                return false;
            }
        }
    }
}
ReservationRepository

簡單起見,我們這裡沒有真正實現數據持久化,只是簡單的模擬。

在我們創建好Web API應用程式時,VS已經添加好了一個預設的HomeController和Index.cshtml View。我們不打算在HomeControllerr 的Action中傳遞Model給View,因為一會要在View中使用JavaScript調用Web API來獲取所有數據。在一個MVC工程中,你可以自由混合地使用普通Controller和API Controller。

修改 Index.cshtml 如下:

@{ ViewBag.Title = "Index";} 
@section scripts { 
    <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script> 
} 
<div id="summaryDisplay" class="display"> 
    <h4>Reservations</h4> 
    <table> 
        <thead> 
            <tr> 
                <th class="selectCol"></th> 
                <th class="nameCol">Name</th> 
                <th class="locationCol">Location</th> 
            </tr>
            </thead> 
        <tbody id="tableBody"> 
            <tr><td colspan="3">The data is loading</td></tr> 
        </tbody> 
    </table> 
    <div id="buttonContainer"> 
        <button id="refresh">Refresh</button> 
        <button id="add">Add</button> 
        <button id="edit">Edit</button> 
        <button id="delete">Delete</button> 
    </div> 
</div> 
 
<div id="addDisplay" class="display"> 
    <h4>Add New Reservation</h4> 
    @{ 
        AjaxOptions addAjaxOpts = new AjaxOptions { 
            // options will go here 
        }; 
    } 
    @using (Ajax.BeginForm(addAjaxOpts)) { 
        @Html.Hidden("ReservationId", 0) 
        <p><label>Name:</label>@Html.Editor("ClientName")</p> 
        <p><label>Location:</label>@Html.Editor("Location")</p> 
        <button type="submit">Submit</button> 
    } 
</div> 
 
<div id="editDisplay" class="display"> 
    <h4>Edit Reservation</h4> 
    <form id="editForm"> 
        <input id="editReservationId" type="hidden" name="ReservationId"/> 
        <p><label>Name:</label><input id="editClientName" name="ClientName" /></p> 
        <p><label>Location:</label><input id="editLocation" name="Location" /></p> 
    </form> 
    <button id="submitEdit" type="submit">Save</button> 
</div>
Index.cshtml

並把 _Layout.cshtml 中的一些沒用的內容清理一下,刪除 /Content/Site.css 中的樣式後添加如下樣式代碼:

table { margin: 10px 0;} 
th { text-align: left;} 
.nameCol {width: 100px;} 
.locationCol {width: 100px;} 
.selectCol {width: 30px;} 
.display { float: left; border: thin solid black; margin: 10px; padding: 10px;} 
.display label {display: inline-block;width: 100px;}
CSS

到這,我們的程式運行起來是這樣的:

接下來我們需要創建一個API Controller,通過它我們可以用JavaScript代碼和Repository的內容進行交互。

右擊  Controllers 文件夾,選擇“添加”--"控制器",在彈出的對話框中修改Controller的名稱為 ReservationController,並從模板中選擇 Empty API。添加好後,修改 ReservationController 如下:

using System.Collections.Generic;
using System.Web.Http;
using WebServices.Models;

namespace WebServices.Controllers {
    public class ReservationController : ApiController {
        IReservationRepository repo = ReservationRepository.getRepository();

        public IEnumerable<Reservation> GetAllReservations() {
            return repo.GetAll();
        }

        public Reservation GetReservation(int id) {
            return repo.Get(id);
        }

        public Reservation PostReservation(Reservation item) {
            return repo.Add(item);
        }

        public bool PutReservation(Reservation item) {
            return repo.Update(item);
        }

        public void DeleteReservation(int id) {
            repo.Remove(id);
        }
    }
}
ReservationController

ReservationController的基類是  System.Web.Http.ApiController,也實現了 IController 介面(在[ASP.NET MVC 小牛之路]09 - Controller 和 Action (1)中有介紹),它和普通Controller的基類System.Web.Mvc.Controller 處理請求的方式基本上是一樣的。

到這我們就已經創建好了一個Web API了。

測試 API Controller

我們先來看看創建好的 API Controller 能否工作,下文將通過 API Controller 對數據的處理結果來解釋API Controller 如何工作。

運行程式,URL定位到 /api/reservation。你看到的結果將依賴於你所使用的版本,如果你使用的是IE 10/11,會彈出一個提示保存文件的對話框,該文件的內容是以下JSON數據:

[{"ReservationId":1,"ClientName":"Adam","Location":"London"}, 
 {"ReservationId":2,"ClientName":"Steve","Location":"New York"}, 
 {"ReservationId":3,"ClientName":"Jacqui","Location":"Paris"}]

如果你使用的是另外一種瀏覽器,如Chrome或Firefox,瀏覽器將顯示如下XML數據:

<ArrayOfReservation> 
    <Reservation> 
        <ClientName>Adam</ClientName> 
        <Location>London</Location> 
        <ReservationId>1</ReservationId> 
    </Reservation> 
    <Reservation> 
        <ClientName>Steve</ClientName> 
       <Location>New York</Location> 
       <ReservationId>2</ReservationId> 
    </Reservation> 
    <Reservation> 
        <ClientName>Jacqui</ClientName> 
        <Location>Paris</Location> 
        <ReservationId>3</ReservationId> 
    </Reservation> 
</ArrayOfReservation>

對於看到的結果,我們有兩點感興趣。第一,我們請求 /api/reservation URL時,伺服器返回了Model對象的列表,根據該列表的數據,我們可以推斷調用的是ReservationController中的 GetAllReservations Action方法。第二,不同的瀏覽器接收到了不同格式的數據,我們可以猜測是由於不同版本的瀏覽器發送請求的方式不一樣。

實際上,之所以會有不同格式的數據結果,是因為 Web API 使用HTTP請求報文頭部的Accept信息來判斷客戶端更願意接收何種類型的數據。IE 接收到JSON格式的數據是因為它發送的Accept頭部信息是:

...
Accept: text/html, application/xhtml+xml, */* 
...

瀏覽器通過這段報文信息告訴伺服器它最想要的是 text/html 內容,其次是 application/xhtml+xml。最後的  */* 意思是如果前兩種不滿足,就接收任何類型的數據。

Web API 支持JSON和XML,但它會優先選擇JSON格式。即IE的發送Accept信息中的 */* 使得Web API生成了JSON格式的數據。下麵是 Chrome 瀏覽器發送的Accept頭部信息:

... 
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
...

這段信息的 application/xml 比 */* 優先順序高,所以Web API選擇為Chrome瀏覽器返回XML格式的數據。

對於Web服務,JSON已經開始大幅度替代XML了,因為XML冗長難以處理,尤其是在JavaScript中。

API Controller 如何工作

通過觀察Web API返回結果的數據,我們似乎有點理解API Controller是如何工作的了。如果你再將請求URL改為 /api/reservation/3,你將看到這樣的JSON數據(使用IE):

{"ReservationId":3,"ClientName":"Jacqui","Location":"Paris"}

這時,你可能更加明白了什麼。這時返回的數據是 ReservationId 為 3 的Reservation對象,我們可以推測Web API根據請求的URL(/api/reservation/3)調用的是GetReservation這個Action方法。這讓我們想到了之前講過的路由知識[ASP.NET MVC 小牛之路]07 - URL Routing

API Controller 在 /App_Start/WebApiConfig.cs 中有它們自己的路由配置,你可以打開該文件看看VS預設註冊好的路由:

public static void Register(HttpConfiguration config) {
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

API Controller使用的路由配置(WebApiConfig.cs)和普通MVC使用的配置(RouteConfig.cs)是在兩個分開的文件中,註冊方法接收的參數(HtttpConfiguration 對象)和添加路由配置的方法(MapHttpRoute)也不一樣。原理都是和 [ASP.NET MVC 小牛之路]07 - URL Routing 講的一樣的,這裡不再累述了。

這個預設的Web API路由有一個靜態片段(api),還有controller和 id片段變數。和MVC路由一個關鍵不同點是,它沒有action片段變數。當然也可以和MVC一樣定義action片段變數,你可以閱讀 Routing in ASP.NET Web API 文章來瞭解更多Web API路由的細節。

當應用程式接收到一個和Web API 路由匹配的請求時,Action方法的調用將取決於發送HTTP請求的方式。當我們用 /api/reservation URL測試API Controller時,瀏覽器指定的是GET方式的請求。API Controller的基類 ApiController根據路由信息知道需要調用哪個Controller,並根據HTTP請求的方式尋找適合的Action方法。

一般約定在Action方法前加上HTTP請求方式名作為首碼。這裡首碼只是個約定,Web API能夠匹配到任何包含了HTTP請求方式名的Action方法。也就是說,本文示例的GET請求將會匹配 GetAllReservations 和 GetReservation,也能夠匹配 DoGetReservation 或 ThisIsTheGetAction。

對於兩個含有相同HTTP請求方式的Action方法,API Controlller會根據它們的參數和路由信息來尋找最佳的匹配。例如請求 /api/reservation URL,GetAllReservations 方法會被匹配,因為它沒有參數;請求 /api/reservation/3 URL,GetReservation 方法會被匹配,因為該方法的參數名和URL的 /3 片段對應的片段變數名相同。我們還可以使用 POST、DELETE 和 PUT請求方式來指定ReservationController的其它Action方法。這就是前文提到的REST的風格。

但有的時候為了用HTTP方式名來給Action方法命名會顯得很不自然,比如 PutReservation,習慣上會用 UpdateReservation。不僅用PUT命名不自然,POST也是一樣的。這時候就需要使用類似於MVC的Controller中使用的Action方法選擇器了。在System.Web.Http 命名空間下同樣包含了一系列用於指定HTTP請求方式的特性,如下所示:

public class ReservationController : ApiController {
    ...
    [HttpPost] public Reservation CreateReservation(Reservation item) {
        return repo.Add(item);
    }
    [HttpPut] public bool UpdateReservation(Reservation item) {
        return repo.Update(item);
    } 
    ...
}

從這我們也看到,在API Controller中使用東西很多都是和MVC中的Controller是一樣的,但它們分別在 System.Web.Http 和 System.Web.Mvc兩個不同的命名空間下,正如本文開始所說,Web API把MVC中的很多東西抽取出來放在System.Web.Http命名空間中,以使Web API作為ASP.NET平臺的一個獨立的核心。

使用 JavaScript 和 Web API 交互

在Scripts文件夾下添加一個Home文件夾,在該文件夾下添加一個 Index.js 文件。在我們寫JS代碼之前,先把這個JS文件引用到Index.cshtml中,如下:

...
@section scripts {
    <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
    <script src="~/Scripts/Home/Index.js"></script>
}
...

在 Index.js 中先把一些基本的方法寫好,如下:

function selectView(view) { 
    $('.display').not('#' + view + "Display").hide(); 
    $('#' + view + "Display").show(); 
} 
function getData() { 
    $.ajax({ 
        type: "GET", 
        url: "/api/reservation", 
        success: function (data) { 
            $('#tableBody').empty(); 
            for (var i = 0; i < data.length; i++) { 
                $('#tableBody').append('<tr><td><input id="id" name="id" type="radio"' 
                + 'value="' + data[i].ReservationId + '" /></td>' 
                + '<td>' + data[i].ClientName + '</td>' 
                + '<td>' + data[i].Location + '</td></tr>'); 
            } 
            $('input:radio')[0].checked = "checked"; 
            selectView("summary"); 
        } 
    }); 
} 
$(document).ready(function () { 
    selectView("summary"); 
    getData(); 
    $("button").click(function (e) { 
        var selectedRadio = $('input:radio:checked') 
        switch (e.target.id) {
            case "refresh":
                getData();
                break;
            case "delete":
                break;
            case "add":
                selectView("add");
                break;
            case "edit":
                selectView("edit");
                break;
            case "submitEdit":
                break;
        }
    });
});
Index.js

我們定義了三個方法。第一個 selectView 方法用於控制div的顯示和隱藏。第二個 getData 方法使用jQuery Ajax通過GET請求/api/reservation URL,並將返回的JSON數據填充到summaryDisplay的table中。第三個是jQuery的ready函數,在頁面內容載入完成時執行。這時的效果如下:

  

接下來一步一步完美編輯、保存和刪除的功能。添加“編輯”功能代碼如下:

...
case "edit":
 $.ajax({ type: "GET", url: "/api/reservation/" + selectedRadio.attr('value'), success: function (data) { $('#editReservationId').val(data.ReservationId); $('#editClientName').val(data.ClientName); $('#editLocation').val(data.Location); selectView("edit"); } });     break;
...

當用戶點擊編輯時,先會取得radio button的value值,並以此組成一個URL(如/api/reservation/1),HTTP請求方式(GET)和URL將使API Controller調用 GetReservation 方法獲取一個Reservation對象的JSON,並將其填充到editDisplay的文本框中。效果如下:

 

下麵再完善一下刪除和保存功能。代碼如下:

...
case "delete":
 $.ajax({ type: "DELETE", url: "/api/reservation/" + selectedRadio.attr('value'), success: function (data) { selectedRadio.closest('tr').remove(); } }); break;
...
case "submitEdit":
 $.ajax({ type: "PUT", url: "/api/reservation/" + selectedRadio.attr('value'), data: $('#editForm').serialize(), success: function (result) { if (result) { var cells = selectedRadio.closest('tr').children(); cells[1].innerText = $('#editClientName').val(); cells[2].innerText = $('#editLocation').val(); selectView("summary"); } } }); break;
...

根據Ajax的DELETE請求,API Controller將調用 DeleteReservation 將選中的Reservation對象從集合中刪除。同樣,根據PUT請求API Controller 將調用PutReservation方法。

最後完善一下添加功能,該ajax請求使用的是 Unobtrusive Ajax,修改 Index.cshtml 如下:

...
<h4>Add New Reservation</h4>
@{
    AjaxOptions addAjaxOpts = new AjaxOptions {
        OnSuccess = "getData", Url = "/api/reservation" 
    };
}
@using (Ajax.BeginForm(addAjaxOpts)) {
    @Html.Hidden("ReservationId", 0)
    <p><label>Name:</label>@Html.Editor("ClientName")</p>
    <p><label>Location:</label>@Html.Editor("Location")</p>
    <button type="submit">Submit</button>
}
...

Ajax.BeginForm生成的表單預設使用的是POST請求,相應的 API Controller將調用PostReservation 方法添加Reservation對象。效果如下:

 

通過這個完整的示例我們可以看到,熟悉MVC後,使用Web API也非常簡單,操作上基本和MVC類似,主要的不同體現在 ApiController 和 Action方法的匹配上。

 


參考:《Pro ASP.NET MVC 4 4th Edition》


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.在使用反射時,反射可以繞過安全訪問級別(private、protected)修飾的類或屬性,來獲取需要的信息。 2.泛型的反射:可以使用Type.ContainsGenericParameters這個屬性來判斷一個類或方法是否包含尚未設置的泛型實參,Type.IsGenericType屬性表示是 ...
  • 從功能上來說,請參考 預告篇,因自知當時預告篇沒有任何含金量,所以並沒有主動推送到首頁,而是私下的給一些人發的。 從個人角度上來說,我希望.net的環境會越來越好,就我自己的成長曲線是從mxdn開始自學、cxdn嘗試解答問題、博客園讀別人博客再到自己寫博客、最後到工作中經常使用到的stackxxxx ...
  • 1.匿名類型:匿名類型是C#3.0新增的特性,是強類型(由編譯器後臺在生成為CIL時,自動聲明的代碼定義類型),聲明與初始化屬性後其屬性是盡讀屬性。只有在屬性的名稱、順序、類型一致時,多個聲明匿名變數才會共用同一個匿名類型。其ToString()方法已重寫了返回的是屬性名稱與值的文本。 2.隱式局部 ...
  • 1.多播委托:由與delegate關鍵字聲明的委托,在編譯後預設繼承Delegate與MulticastDelegate類型,所以聲明的委托自然就含有多播委托的特性,即一個委托變數可以調用一個方法鏈(多個相同簽名的方法)。在C#中,多播委托的實現是一個通用的模式,目的是避免大量的手工編碼,這個模式稱 ...
  • Unity下GL沒有畫圓的函數,只能自己來了。 如果能幫到大家,我也很高興。 雖然沒有畫圓的函數,但是能畫直線,利用這一點,配合微積分什麼的,就可以畫出來了。反正就是花很多連在一起的直線,每條直線足夠短的時候,就足夠圓了 參數分別為: x,y,z 中心點三維坐標, r 圓的半徑, accuracy ...
  • 魔方 是一個基於 ASP.NET MVC 的 用戶許可權管理平臺,可作為各種信息管理系統的基礎框架。 演示:http://cube.newlifex.com 源碼 演示賬號:admin/admin 源碼: https://git.newlifex.com/NewLife/X/Tree/master/N ...
  • 先上圖: 操作方法: 1、先設置一下gridview中屬性:IndicatorWidth,一般為:40。如下圖;(一般可以顯示5位數字。如要更長顯示,自己測試一下。) 2、找到gridview中的:CustomDrawRowIndicator事件,輸入如下麵代碼: 1 private void gv ...
  • 參考頁面: http://www.yuanjiaocheng.net/CSharp/csharp-class.html http://www.yuanjiaocheng.net/CSharp/csharp-variable.html http://www.yuanjiaocheng.net/CSha ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...