亚洲精品亚洲人成在线观看麻豆,在线欧美视频一区,亚洲国产精品一区二区动图,色综合久久丁香婷婷

              當(dāng)前位置:首頁 > IT技術(shù) > Windows編程 > 正文

              《ASP.NET Core 與 RESTful API 開發(fā)實(shí)戰(zhàn)》-- (第6章)-- 讀書筆記(下)
              2021-10-22 16:52:58


              第 6 章 高級(jí)查詢和日志

              6.3 排序

              RESTful API 在實(shí)現(xiàn)排序時(shí)應(yīng)支持對(duì)集合資源的一個(gè)或多個(gè)屬性進(jìn)行排序

              示例對(duì) authors 資源按照其屬性 Age 升序排序,再按 BirthPlace 屬性降序排序:??https://localhost:5000/api/authors??? orderby=age,birthplace desc

              在 ASP.NET Core 中實(shí)現(xiàn)排序,與過濾和查詢一樣,通過對(duì)查詢字符串中的排序項(xiàng)進(jìn)行解析,然后在分頁操作之前,將它們指定的排序方式進(jìn)行排序,并最終返回結(jié)果

              首先在 AuthorResourceParameters 中添加屬性

              public string SortBy { get; set; } = "Name";


              接下來,在 AuthorRepository 的 GetAllAsync 方法中,使用 OrderBy 子句來實(shí)現(xiàn)查詢

              if (parameters.SortBy == "Name")
              {
              queryableAuthors = queryableAuthors.OrderBy(author => author.Name);
              }


              由于 LINQ 的 OrderBy 擴(kuò)展方法不支持直接使用字符串,當(dāng)資源支持多個(gè)排序字段時(shí),一一判斷比較繁瑣,而且在進(jìn)行后續(xù)排序時(shí),還應(yīng)該使用 ThenBy 子句,使得判斷更加復(fù)雜,幸運(yùn)的是可以借助第三方庫 System.Linq.Dynamic.Core 實(shí)現(xiàn)動(dòng)態(tài) LINQ 查詢

              System.Linq.Dynamic.Core 除了支持直接使用屬性名排序之外,還支持多屬性排序,多個(gè)屬性之間使用逗號(hào)隔開,每個(gè)屬性默認(rèn)以升序排序,若要使用降序排序,則應(yīng)在屬性名后添加 desc 或 descending,并以空格隔開

              nuget 安裝該庫

              Install-Package Microsoft.EntityFrameworkCore.DynamicLinq


              安裝成功后修改 AuthorRepository 的 GetAllAsync 方法

              var orderedAuthors = queryableAuthors.OrderBy(parameters.SortBy);

              return PagedList<Author>.CreateAsync(orderedAuthors, parameters.PageNumber, parameters.PageSize);


              排序選項(xiàng) SortBy 同樣作為分頁數(shù)據(jù)的一部分,應(yīng)返回給客戶端,在 AuthorController 的 GetAuthorsAsync 方法生成分頁數(shù)據(jù)時(shí),添加代碼

              previousePageLink = pagedList.HasPrevious
              ? Url.Link(nameof(GetAuthorsAsync), new
              {
              pageNumber = pagedList.CurrentPage - 1,
              pageSize = pagedList.PageSize,
              birthPlace = parameters.BirthPlace,
              searchQuery = parameters.SearchQuery,
              sortBy = parameters.SortBy
              })
              : null,
              nextPageLink = pagedList.HasNext
              ? Url.Link(nameof(GetAuthorsAsync), new
              {
              pageNumber = pagedList.CurrentPage + 1,
              pageSize = pagedList.PageSize,
              birthPlace = parameters.BirthPlace,
              searchQuery = parameters.SearchQuery,
              sortBy = parameters.SortBy
              })
              : null


              為了解決 DTO 與實(shí)體屬性名不同時(shí)的映射問題,可以在程序中添加一個(gè)字典,來存儲(chǔ)需要進(jìn)行映射的屬性及其對(duì)應(yīng)的屬性名

              然而對(duì)于 AuthorDto 中的 Age 屬性和 Author 中的 BirthDate 屬性,其排序規(guī)則正好相反,即年齡越小,出生日期越靠后,這種情況下,除了要考慮映射外,還應(yīng)考慮方向

              namespace Library.API.Helpers
              {
              public class PropertyMapping
              {
              public bool IsRevert { get; private set; }
              public string TargetProperty { get; private set; }

              public PropertyMapping(string targetProperty, bool isRevert = false)
              {
              IsRevert = isRevert;
              TargetProperty = targetProperty;
              }
              }
              }


              接著,可以在 AuthorRepository 中定義一個(gè)字典

              private Dictionary<string, PropertyMapping> mappingDict = null;

              public AuthorRepository(DbContext dbContext) : base(dbContext)
              {
              mappingDict = new Dictionary<string, PropertyMapping>(StringComparer.OrdinalIgnoreCase);
              mappingDict.Add("Name", new PropertyMapping("Name"));
              mappingDict.Add("Age", new PropertyMapping("BirthDate", true));
              mappingDict.Add("BirthPlace", new PropertyMapping("BirthPlace"));
              }


              為了使這一分析邏輯的通用性和 GetAllAsync 的方法簡(jiǎn)潔,可以將它放到一個(gè)擴(kuò)展方法中

              namespace Library.API.Extentions
              {
              public static class IQueryableExtention
              {
              private const string OrderSequence_Asc = "asc";
              private const string OrderSequence_Desc = "desc";

              public static IQueryable<T> Sort<T>(this IQueryable<T> source, string orderBy,
              Dictionary<string, PropertyMapping> mapping) where T : class
              {
              var allQueryParts = orderBy.Split(',');
              List<string> sortParts = new List<string>();
              foreach (var item in allQueryParts)
              {
              string property = string.Empty;
              bool isDescending = false;
              if (item.ToLower().EndsWith(OrderSequence_Desc))
              {
              property = item.Substring(0, item.Length - OrderSequence_Desc.Length).Trim();
              isDescending = true;
              }
              else
              {
              property = item.Trim();
              }

              if (mapping.ContainsKey(property))
              {
              if (mapping[property].IsRevert)
              {
              isDescending = !isDescending;
              }

              if (isDescending)
              {
              sortParts.Add($"{mapping[property].TargetProperty} {OrderSequence_Desc}");
              }
              else
              {
              sortParts.Add($"{mapping[property].TargetProperty} {OrderSequence_Asc}");
              }
              }
              }

              string finalExpression = string.Join(',', sortParts);
              source = source.OrderBy(finalExpression);
              return source;
              }
              }
              }


              在 Sort 邏輯內(nèi)部中,通過解析得到最終的排序表達(dá)式,并使用 System.Linq.Dynamic.Core 庫中的 OrderBy 對(duì) IQueryable 對(duì)象排序,并返回排序后的結(jié)果

              接著,修改 AuthorRepository 的 GetAuthorsAsync 方法中的返回結(jié)果語句

              //var orderedAuthors = queryableAuthors.OrderBy(parameters.SortBy);
              var orderedAuthors = queryableAuthors.Sort(parameters.SortBy, mappingDict);


              運(yùn)行程序,請(qǐng)求 URL:??https://localhost:5001/api/authors?pageSize=3&sortby=birthplace,age??

              6.4 日志與異常

              ASP.NET Core 內(nèi)部集成了日志的功能,但是并不支持向文件輸出日志,因此我們通過 NLog 實(shí)現(xiàn)

              安裝nuget

              Install-Package NLog.Extensions.Logging


              NLog 通過 XML 形式的文件來配置它的使用方式,添加一個(gè) nlog.config

              <?xml version="1.0" encoding="utf-8" ?>
              <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

              <targets>
              <target name="asyncFile" xsi:type="AsyncWrapper">
              <target name="log_file" xsi:type="File"
              fileName="${basedir}/Logs/${shortdate}/${shortdate}.txt"
              layout="${longdate} | ${message} ${onexception:${exception:format=message} ${newline} ${stacktrace} ${newline}"
              archiveFileName="${basedir}/archives/${shortdate}-{#####}.txt"
              archiveAboveSize="102400"
              archiveNumbering="Sequence"
              concurrentWrites="true"
              keepFileOpen="false" />
              </target>
              <target name="console" xsi:type="ColoredConsole" layout="[${date:format=HH:mm:ss}]:${message} ${exception:format=message}" />
              </targets>

              <rules>
              <logger name="*" minlevel="Error" writeTo="asyncFile" />
              <logger name="*" minlevel="Debug" writeTo="console" />
              </rules>
              </nlog>


              在 Configure 添加如下代碼

              public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IMapper mapper, ILoggerFactory loggerFactory)
              {
              loggerFactory.AddNLog();
              loggerFactory.ConfigureNLog("nlog.config");
              。。。


              在 Controller 注入使用

              public IMapper Mapper { get; set; }
              public IRepositoryWrapper RepositoryWrapper { get; set; }
              public ILogger<AuthorController> Logger { get; set; }

              public AuthorController(IRepositoryWrapper repositoryWrapper, IMapper mapper, ILogger<AuthorController> logger)
              {
              RepositoryWrapper = repositoryWrapper;
              Mapper = mapper;
              Logger = logger;
              }


              在 MVC 應(yīng)用程序中,可以通過異常過濾器 IExceptionFilter 處理異常

              首先定義 ApiError

              namespace Library.API.Helpers
              {
              public class ApiError
              {
              public string Message { get; set; }
              public string Detail { get; set; }
              }
              }


              接著,添加一個(gè)過濾器

              namespace Library.API.Filters
              {
              public class JsonExceptionFilter : IExceptionFilter
              {
              public IHostEnvironment Environment { get; }
              public ILogger Logger { get; }

              public JsonExceptionFilter(IHostEnvironment environment, ILogger<Program> logger)
              {
              Environment = environment;
              Logger = logger;
              }

              public void OnException(ExceptionContext context)
              {
              var error = new ApiError();
              if (Environment.IsDevelopment())
              {
              error.Message = context.Exception.Message;
              error.Detail = context.Exception.ToString();
              }
              else
              {
              error.Message = "服務(wù)器出錯(cuò)";
              error.Detail = context.Exception.Message;
              }

              context.Result = new ObjectResult(error)
              {
              StatusCode = StatusCodes.Status500InternalServerError
              };

              StringBuilder sb = new StringBuilder();
              sb.AppendLine($"服務(wù)器發(fā)生異常:{context.Exception.Message}");
              sb.AppendLine(context.Exception.ToString());
              Logger.LogCritical(sb.ToString());
              }
              }
              }


              最后將它添加到 MVC 配置中,即可生效

              services.AddMvc(configure =>
              {
              configure.Filters.Add<JsonExceptionFilter>();
              。。。


              《ASP.NET Core 與 RESTful API 開發(fā)實(shí)戰(zhàn)》-- (第6章)-- 讀書筆記(下)_xml


              本文摘自 :https://blog.51cto.com/u

              開通會(huì)員,享受整站包年服務(wù)立即開通 >