基于 Vue.js 之 iView UI 框架非工程化实践记要 使用 Newtonsoft.Json 操做 JSON 字符串 基于.net core实现项目自动编译、并生成nuget包 webpack

基于 Vue.js 之 iView UI 框架非工程化实践记要

 

Markdown

像咱们平日里作惯了 Java 或者 .NET 这种后端程序员,对于前端的认识还经常停留在 jQuery 时代,包括其插件在须要时就引用一下,不须要就删除。故观念使然,尽管 Nuget 和 Maven 用得顺溜,但对 NPM 仍不带感,兴许是周边无人带动的稀薄气氛,也或者是没参加过相似的大型活动,因而在自发性上差了许多。再者,我不用 MVVM 模式,领导也不会扣绩效。javascript

为了快速体验 MVVM 模式,我选择了非工程化方式来起步,并选择使用 Vue.js,以及基于它构建的 iView UI 框架。css

Vue.js 是美籍华人尤雨溪创做的,那会儿他还在 Google 工做,他自感 Angular.js 繁杂,进而自创了更为简洁易用的 Vue.js。html

iView UI 是由 90 后梁灏[hào]创做,网名 Aresn,在大数据公司 TalkingData 负责可视化基础架构,更了不得的是他还出了《Vue.js实战》一书,我是在“双十一”的前一天买的,行文措词简洁,表意直达困惑,入门很迅速,是我喜欢的风格。花了一周时间扫完了前十二章内容,用 WebStorm 练习了大部分实例,尽管书中用一整章内容介绍了 webpack 工程化构建方案,但因为我惯性使然,仍是选择对其跳过而使用了非工程化方式来体验 Vue.js,其实多少有失暴殄。无奈,毕竟才学了一周,后期时间充裕了再接着分享工程化构建的学习心得吧。前端

1、 MVVM 模式

Vue.js 比较显著的特征是解耦了视图和数据,也就是说视图的变化再也不须要命令式编程去显式改变,只要修改完数据就能当即自动同步,这是比较大的一个思惟模式的转变,另外一个就是组件化思惟俯首皆是,这样开发一个应用就至关是在搭积木。vue

其实以上对 Vue.js 所阐述的优势也正是 MVVM 模式的写照,它原是由 MVC 所衍生,即当视图层发生变化时,会自动更新到视图模型上,反之亦然,这就是常说的双向绑定,上一张图吧:java

Markdown

甭管这图是否好理解,通俗地来说,MVVM 这种模式拆分了视图和数据,这样咱们在开发时只要关心数据自己便可,而后视图 DOM 这方面会由 Vue.js 自动解决。webpack

2、非工程化起步

为了能支撑起一个最基本的应用,须要引入如下几个必要文件:git

  1. vue.min.2.5.3.js,vue.js 库
  2. iview.2.7.0.css,iView 样式文件
  3. iview.min.2.7.0.js,iView 库
  4. iview /locale/zh-CN.js 语言包
  5. iview /font 字体包

下载 Vue.js

来到 Github 上的 Vue 项目,直接下载 Zip 源码:程序员

Markdown

在 dist 目录中就能够找到 vue.js 文件:es6

Markdown

根据不一样的环境选择一个版本便可,至此第 1 步就搞定了。

下载 iView 系列文件

在 iView 官网的“组件” / “安装” 页面的开头处发现了这个连接:https://unpkg.com/iview/ ,经过它能够查看到 dist 目录:

Markdown

必要文件都在这里,这些文件没法打包下载,我采起的笨办法是逐个点开,而后复制其中的内容。

在获取 iView 相关的 js 和 css 方面还有一个办法,仔细观察官网给出的 CDN 地址分别为:

我尝试将它们放在浏览器里进行访问:

Markdown

发现地址有变动,不过这并没有大碍。

至此,将各个文件放在指望的位置便可:

Markdown

该图中各文件的摆放并非很严谨,你们按本身习惯来便可。

3、实例演练

完成以上的准备工做后,就能够结合 iView UI 来正式开发了,接下来基于 table 表格组件演示一下购物车的基本操做。

引入资源

通过起步工做的筹备,能够在新建页面中逐个地引入这些资源。

HTML head 部分
<head> <meta charset="UTF-8"> <title>购物车实例</title> <link rel="stylesheet" href="iViewContent/iview.2.7.0.css"> <script src="utility_js/vue.min.2.5.3.js"></script> <script src="utility_js/iview.min.2.7.0.js"></script> <script src="iViewContent/locale/zh-CN.js"></script> <script> iview.lang('zh-CN'); </script> </head>

按一向的方式引用,样式居前,随后紧跟着 vue.js 和 iView.js,以及 iView 中文语言包 zh-CN.js,而后当即调用 lang 方法使其生效。

绑定数据

首先把数据绑定起来,从而看一看总体效果,至于其余的行为操做先无论:

Markdown

HTML body 部分
<body> <div id="app"> <i-table id="datatable1"  size="small"  :columns="columns"  :data="cartList"  stripe  highlight-row> </i-table> </div> <script src="iViewUI_cart.js"></script> </body>

组件 i-table 最核心的两个属性分别是 columns 和 data,columns 是列定义,data 则为数据。

这两个属性都添加了冒号(:)语法糖,它指代的是 v-bind 指令,表示这个属性的值是动态绑定的,这样在运行过程当中发现数据有变动时,表格视图也会迅速的变动。

iViewUI_cart.js 脚本部分
var cart = new Vue({ el: '#app', data: function () { return { cartList: [ {id: 1, name: 'iPhone X', price: 8300.05, count: 1}, {id: 2, name: 'MacBook Pro', price: 18800.75, count: 3}, {id: 3, name: 'Mate 10 Porsche', price: 16600.00, count: 8} ], columns: [ { title: '名称', key: 'name' }, { title: '单价', key: 'price' }, { title: '数量', key: 'count' } ] } }, methods: {} });

该文件是与页面对应的业务脚本,整个文件就负责 new 一个 Vue 实例,并将其赋值给了变量 cart,能够看到的 data 包含了两个属性,即表示数据源的 cartList 和 列定义的 columns,两者正好与上述 i-table 的核心属性相映射。

再次值得注意的是 data,它的值须要以匿名函数的形式进行书写,即:

function () { return {} }

如此,在其 columns 中出现的 Render 函数体内才能正常经过 this 访问到 methods 中定义的方法。固然本次演示是经过 cart 对象来访问,故不受此影响。

运行页面后,数据便可绑定成功。

添加操做所需按钮

数据呈现出来后,就能够补充必要的按钮了:

Markdown

这一步简单,只须要修改一下 columns 属性,追加一项“操做”列,添加三个按钮:

{ title: '数量', key: 'count' }, { title: '操做', render: (h, params) => { return h('div', [ h('Button', { props: { type: 'primary', size: 'small' }, style: { marginRight: '5px' }, on: { click: () => { console.info('减小数量'); cart.reduceQuantity(params.row.id); } } }, '-'), h('Button', { props: { type: 'primary', size: 'small' }, style: { marginRight: '5px' }, on: { click: () => { console.info('增长数量'); cart.increaseQuantity(params.row.id); } } }, '+'), h('Button', { props: { type: 'error', size: 'small' }, style: { marginRight: '5px' }, on: { click: () => { console.info('删除当前项'); cart.deleteItem(params.row.id); } } }, '删除') ]); } }

在这里使用到了 Render 函数,该函数的内部机制略显复杂,做为初步演示只需依样画葫芦便可。

说到 Render 函数,还须要再强调一下在其内部对 methods 中所定义方法的调用,若是试图经过 this 来调用方法(好比 reduceQuantity),那么 Vue 实例中 data 的值须要使用匿名函数的方式来表达;反之,如果经过 Vue 实例 cart 来调用,则无此顾虑,即 data 的值使用一向的对象大括号({})来表达便可。

添加操做所需方法

操做按钮已经添加成功了,那就须要有对应的方法去执行,在 Vue.js 中,方法都定义在 methods 属性中。

减去数量

首先关注一下“减去数量”的定义:

methods: { reduceQuantity: function (id) { for (let i = 0; i < this.cartList.length; i++) { if (this.cartList[i].id === id) { this.cartList[i].count--; break; } } } }

经过遍历找到目标记录,并将其 count 属性减一,如同 MVVM 的定义,当数据变动的时候,视图也跟随着变化。

但凡是存在于购物车内的商品,其数量至少应该为 1,为防止减到 0,不妨再加一个判断使其逻辑更为完美:

methods: { reduceQuantity: function (id) { for (let i = 0; i < this.cartList.length; i++) { if (this.cartList[i].id === id) { if (this.cartList[i].count > 1) { this.cartList[i].count--; } break; } } } },
增长数量
methods: { increaseQuantity: function (id) { for (let i = 0; i < this.cartList.length; i++) { if (this.cartList[i].id === id) { this.cartList[i].count++; break; } } } }

只须要针对 count 属性作 +1 操做便可。

删除
deleteItem: function (id) { for (let i = 0; i < this.cartList.length; i++) { if (this.cartList[i].id === id) { // 询问是否删除 this.$Modal.confirm({ title: '提示', content: '肯定要删除吗?', onOk: () => { this.cartList.splice(i, 1); }, onCancel: () => { // 什么也不作 } }); } } }

在删除逻辑中,当遍历到目标记录时,会询问用户是否真的要删除当前记录,这里用到了 $Modal 对话框,若是用户点击肯定,那么就执行真正的删除,看一看效果:

Markdown

很是漂亮考究的 iView Modal 对话框,使人赏心悦目,一见钟情。

至此,针对 Vue.js 和 iView 框架的体验就告一段落,后面抽时间再学习一下组件和 Render 函数,提高一下内功修养。

 

 

 

对 Newtonsoft.Json 的应用能够说司空见惯,在 JSON 格式层级不深的状况下使用很方便,但有时遇到的 JSON 字符串层级很是多,且真正须要的数据每每都“埋”得很深,这时若是去定义一个与之对应的多层嵌套实体类就显得不划算,下面经过实例来演示如何一步到位抓取到指望的数据(集)。

1、把实体类转化为 JSON 字符串

1. 为实体类赋值

SenderFromMQSearch senderFromMQSearch = new SenderFromMQSearch(); senderFromMQSearch.StartTime = new DateTime(2017, 9, 10); senderFromMQSearch.EndTime = new DateTime(2017, 9, 10); senderFromMQSearch.FlowType = "DataSender";

2. 序列化

经过简单的序列化后,能够将 C# 实体类转换为 JSON 格式的字符串

string paramsText = JsonConvert.SerializeObject(senderFromMQSearch);

转换后其格式相似以下:

{\"StartTime\":\"2017-09-10\", \"EndTime\":\"2017-09-10\", \"FlowType\":\"DataSender\", \"SiteNo\":\"\"}

2、提取 JSON 字符串中部分属性的值

JSON 属性的值有多种类型,好比 String、Array 等,经过属性提取到对应的值时须要特别留意这些类型,从而作出正确地转化。

好比现借助上面的查询实体类,以及前文介绍的 Chloe.ORM 查询到一段结果集,其形式如同这样一段 JSON 字符串:

{ "Status": true, "Msg": "成功", "Data": { "SiteData": [ { "SiteNo": "200012", "SiteName": "上海公司", "Total": 100 }, { "SiteNo": "214001", "SiteName": "无锡分销部", "Total": 200 } ] } }

并将该字符串存储在变量 resultText 中。

1. JObject

将其转化为 JSON 对象,即 JObject:

JObject jObj = JObject.Parse(resultText);

接着能够尝试获取"Data"属性的值:

jObj["Data"].ToString();

其值的形式为:

{ "SiteData": [ { "SiteNo": "200012", "SiteName": "上海公司", "Total": 100 }, { "SiteNo": "214001", "SiteName": "无锡分销部", "Total": 200 } ] }

2. JArray

这时发现,真正指望的值其实还在属性“SiteData”里面,那不如索性一步到位:

jObj["Data"]["SiteData"].ToString();

此时,其值的形式为:

[
  { "SiteNo": "200012", "SiteName": "上海公司", "Total": 100 }, { "SiteNo": "214001", "SiteName": "无锡分销部", "Total": 200 } ]

可见这是一个数组格式的字符串,能够尝试将其转化为数组对象,即 JArray:

JArray siteDataArray = JArray.Parse(jObj["Data"]["SiteData"].ToString());

3. JArray 转换为 List

对于该数组中的每个对象,都存在三个属性:SiteNo、SiteName,以及 Total,为了更方便地操做这些数据,能够考虑泛型集合。

首先来定义实体类:

public class SiteInfo { public string SiteNo { get; set; } public string SiteName { get; set; public int Total { get; set; } }

能够看出,实体类的属性实际上与数组中每个对象的属性相对应。

接着来遍历一下这个数组,对于数组中的每个对象都会有一个实体对象(siteInfo)与之对应,而后将该实体对象(siteInfo)逐个地添加至泛型集合(siteInfoList)便可。

List<SiteInfo> siteInfoList = new List<SiteInfo>(); foreach (var item in siteDataArray) { SiteInfo siteInfo = new SiteInfo(); siteInfo.SiteNo = item["SiteNo"].ToString(); siteInfo.SiteName = item["SiteName"].ToString(); siteInfo.Total = (int)item["Total"]; siteInfoList.Add(siteInfo); }

至此,核心数据就倒腾到泛型集合中,接下来借助 Linq 就能够玩各类花样了。

 

 

近期想对本身的项目增长自动编译并生成nuget包,网上资料很多。但总还有迷糊的时候。首先:此解决方案包含多种版本的项目,如:有编译必须是x86平台,以及还有传统的.net foramework项目,以及多版本的.net core项目等。找到通用的解决方案仍是用了很多的时间。本文章就对此作下自我总结。望对同仁有所帮助。

1、遇到的问题,以及解决办法

1.1 不一样平台的编译怎么办

      .net能够将dll(或者说是项目)编译成x8六、x6四、anycpu 等至少三种平台代码。但若是用dotnet build生成项目时,默认是anycpu,须要经过platform参数来执行平台。但是,若是你一个解决方法中即有x86项目、又有anycpu项目可怎么是好呢。解决办法:建立两个sln文件,一个用x86平台的编译,一个用于anycpu平台的编译。

1.2 传统.net framework项目,怎么用dotnet 进行编译

这个问题其实最终的解决办法也很简易,就是将.net framework项目直接迁移成dotnet 可编译的项目。步骤以一个.net 4.6.1项目为例:

  • 传统的.net framework项目

  • 卸载此项目,并编辑.csproj文件

当前步骤编辑好的.csproj文件以下:

复制代码
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net461</TargetFramework>
  </PropertyGroup> 

</Project>
复制代码
  • 移除Properites中的assemblyInfo文件

由于dotnet 会自动建立assemblyInfo相关的信息文件,若是要自定义,能够找到相关资料进行限制

注意,少了assemblyinfo.cs文件。

  • 还原相关引用

生成项目,根据提示引用相关类型,默认调整后的是 类库 文件,若是须要变成 应用执行程序,能够本身修正便可。

  • 生成并运行

在还原好依赖项,以及调整好输出类型后,便可完成 项目的迁移。最终的项目结果:

以及最终生成的csproj文件:

复制代码
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net461</TargetFramework>
    <ApplicationIcon />
    <OutputType>Exe</OutputType>
    <StartupObject />
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\..\src\SAM.Configuration\SAM.Configuration.csproj" />
    <ProjectReference Include="..\..\src\SAM.Framework\SAM.Framework.csproj" />
  </ItemGroup> 

</Project>
复制代码
  • 多版本的支持

     若是你须要的项目即能在.net40,.net461, .net core2.0上运行,那就须要作到多版本兼容。方式即为简单,须要将TargetFramework改成TargetFrameworks,而后多版本用分号隔开便可:

<TargetFrameworks>net461;net40;netcoreapp2.0</TargetFrameworks>

2、统一实现

在解决了上述三个主要问题以后,实现自动编译和出包就很简单。咱们能够写一个ps1文件来实现,也就是powershell脚本,总体代码以下:

复制代码
#定义全局变量

$destFolder = Get-Location;
$version = "1.0.0.0-alpha";

#编译anycpu的包
$anycpuPath = $destFolder.Path + "\..\SAM.Framework.anycpu.sln";
dotnet pack $anycpuPath --output $destFolder.Path /p:PackageVersion=$version;

#编译x86的包
$anycpuPath = $destFolder.Path + "\..\SAM.Framework.x86.sln";
dotnet pack $anycpuPath --output $destFolder.Path /p:PackageVersion=$version /p:platform=x86;

pause
复制代码

是否是很简单,几句代码就是实现将全部项目生成nuget包。且还能够分平台实现。核心参数说明:

  • /p:是设置msbuild相关参数的入口,如:包版本(版本在dotnet core上好像此支持三个阶段,如:1.0.0这种,而四阶段没有了),以及平台等。
  • --output:生成的包输出文件夹

此命令还有些不足点,如 anycpu和x86中都编译同一个项目,后者的编译会覆盖前者(感受能够用nuget包依赖来解决)。

3、后话

     在解决此问题以前,本人也走了很多的弯路。如寻找msbuild与dotnet build的兼容方案,以及如何动态修正sln文件等,但还好最终仍是解决解决。回过头来看,其实遇到问题换个角度,打开思惟才是最重要的。

 

 

 

上周的某一天,和一位一样是前端技术极度爱好的开发者朋友聊天,他在提出了一个问题,他写的vue程序为何在dev模式运行良好,而在production模式就直接报错了。这让我感到惊讶,还有这么神奇的事情。今就把这个历险记道给大伙听听,看能从中学习到什么?

1、还原现场

朋友在看到个人惊讶后,分分就把他出错的demo发给了,本地运行,事故现场重现: image

2、排查嫌疑对象

既然现象是必现,要么是本身的代码出了问题,要么就是vue有Bug(内心莫名的偷笑,大伙都懂的)。

2.1 代码文件结构和源码展现

image
从代码结构看,没有好说的。就是用vue-cli建立的模板开发项目,其保增长了service层而已。通过我多年来的经验,将嫌疑放到了service/index.js和components/HellowWorld.vue两个文件上。

  • service/index.js代码
复制代码
let item = {};
item.result = 22222;
item.do = callBack => {
  return callBack({ result: this.a.result });
};

export default item;
复制代码
  • HelloWorld.vue代码(只展现了js代码部分)
复制代码
import service from "@/service/index"
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  mounted () {
    service.do(item => {
      this.msg = item.result
    })
  }
}
复制代码

简要逻辑说明:

  • HelloWorld.vue引用了service/index.js文件
  • service/index.js中定义了do方法,且接受一个callback参数(使用了es6的箭头函数)
  • HelloWorld.vue在mounted方法中调用了do方法,且传入了一个函数表达式(也使用了箭头函数)

2.2 报错位置侦查

经过运行结果对比图,能够看出production模式下的运行是有报错,在达里咱们放大他的报错位置:
image
     看到这里,你是否有想破口大骂的冲动,怎么会this.a.result呢,这代码明显有错误吧。而后我迅速查阅了他给的demo代码,见service/index.js中的do方法,确实是怎么样写的。马上,我略带鄙视的口吻质问个人那位朋友,你这个几年的代码白写了吧,竟然能犯这么低级的错误。我直接把这个错误现场图扔给了他。   

     立刻,他回了一个更为鄙视的表情,那为何个人dev模式能正常运行呢。我当即无语且尴尬。由于确实他的dev模式运行是正常的,只有在production模式下才出的问题啊。

2.3 重点分析嫌疑对象

    通过上述的分析和折腾,咱们能够初步肯定问题点就在service/index.js中do方法中和this上。也就是说在dev模式下这个this.a上是有result这个属性的,而在production模式下this连这个a属性都没有了。

     做为老鸟的我,忽然想到,dev模式和production模式都是运行在有sourcemap的的状况下的。这很不利用咱们看编译后的代码。因而,我关闭了chrome浏览器的sourcemap功能,两种模式下代码以下:

  • dev模式下的运行代码:
    image
    注意三个红框处的代码,webpack在dev模式下代码文件是没有合并成一个文件的,而是遵行commanJs规范,进行模式化加载的,而他对这个service/index.js这个模式导出时,用的名称正是a。也就是解释了在dev模式下this.a为何会有效,他的this.a.result有值,则是由于他虽然是单文件模式化加载,但其文件中的js代码仍是被bable作了转换,将箭头运算符转换为了es5可执行的代码。因此this.a.result是有值的。

 

  • production模式下的运行代码:
    image
         看这段代码是否有些头大,其实从中咱们只须要关心l这个变量的值,经测试发现,他的值不service/index.js中导出的对象,而是浏览器全局对象window。这就是为何production模式下的代码不能正常运行的问题了。

3、个人推理和总结

      经过上述分析,能够大体推理出webpack在dev模式下是按照commonJs模式将各个文件独立模式化加载和引用,而Build以后,各个文件模块被合并成了一个,且对servcie/index.js进行了直接导出。再中上箭头函数对this指向的处理,就形成了this.a无效了。
     在这个demo中就算把service/index.js中的this指向处理好了,但其值仍是会正常显示,缘由在于vue组件中的mounted方法中也用到了箭头函数,其this的指向在运行时也会不正确。具体解释以下:

注意,不要在实例属性或者回调函数中(如 vm.$watch('a', newVal => this.myMethod()))使用箭头函数。由于箭头函数绑定父级上下文,因此 this 不会像预想的同样是 Vue 实例,并且 this.myMethod 是未被定义的。

vue官网说明地址:https://cn.vuejs.org/v2/guide/instance.html

3.1 缘由总结

  • this.a为何能够访问,是由于webpack的dev下编译是单个文件模式化引用致使的
  • vue组件的mounted中用不可以使用箭头函数,这个vue的特性,官网可见。
  • 示例代码下载

 

 

这样入门asp.net core 之 静态文件

 

本文章主要说明asp.net core中静态资源处理方案:

1、静态文件服务

首先明确contentRoot和webroot这两个概念

  • contentRoot:web的项目文件夹,其中包含webroot和其余bin等其余文件夹
  • webroot:webroot是站点文件夹,可用url访问的文件夹。默认为:"contentroot/wwwroot"
  • 实现代码以下
    Program中的代码
复制代码
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory()) //设置contentroot
    .UseWebRoot("mywwwroot") //设置webroot
    .UseUrls("http://*:5000") //其余电脑能够用ip地址访问
    .Build();
复制代码

     StartUp中的代码

复制代码
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseStaticFiles();//开启静态文件访问
    //自定义静态文件访问
    app.UseStaticFiles(new StaticFileOptions(){
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "mystatic")),
        RequestPath = new PathString("/sam/static")
    });
     //配置mvc
    app.UseMvc(routers=>{
        routers.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
}
复制代码

效果图下图:
image

1.1 目录浏览

实现代码以下:

复制代码
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{  
    app.UseDirectoryBrowser(new DirectoryBrowserOptions(){
        FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Controllers")),
        RequestPath = new PathString("/controller")
    }); 
}
复制代码

image

1.2 默认文档

app.UseDefaultFiles方法开启默认访问的配置,配置项用DefaultFilesOption类表示,代码以下:

复制代码
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{  
    //默认文件
    DefaultFilesOptions defaultFiles = new DefaultFilesOptions();
    defaultFiles.DefaultFileNames.Clear();
    defaultFiles.DefaultFileNames.Add("myindex.html");
    app.UseDefaultFiles(defaultFiles); 
    
    app.UseStaticFiles(); //开启静态文件访问
}
复制代码

注意此配置必定要在全部Use以前,不然设置不生效

1.3 UseFileServer

UserFileServer包含了UseStaticFiles, UseDefaultFiles, UserDirectoryBrowser的功能

复制代码
app.UseFileServer(new FileServerOptions(){
    EnableDefaultFiles, //是否开启默认文档
    EnableDirectoryBrowsing, //是否开启目录浏览
    DefaultFilesOptions, //默认文件设置
    StaticFileOptions, //静态资源访问设置
    DirectoryBrowserOptions, //目录浏览设置
});
复制代码

2、静态文件受权

静态模块是不对文件进行权限检查的,包含wwwroot下的文件和文件夹。若是相进行权限控制,可使用action返回一个FileResult来实现:

复制代码
private string basePath = Common.Uitls.HostingEnvironment.ContentRootPath;
public FileResult Index(int id){
    if(id == 1){
        return new PhysicalFileResult(Path.Combine(basePath, "aufolder","author.html"), "text/html");
    }
    return new PhysicalFileResult(Path.Combine(basePath, "error.html"), "text/html");;
}
复制代码

3、FileExtensionContentTypeProvider类的使用

此类包含一个将文件扩展名映射到MIME内容类型的集合,代码以下:

复制代码
FileExtensionContentTypeProvider provider=new FileExtensionContentTypeProvider();
provider.Mappings.Add(".sam", "text/plain");
//自定义静态文件访问
app.UseStaticFiles(new StaticFileOptions(){
    FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "mystatic")),
    RequestPath = new PathString("/sam/static"),
    ContentTypeProvider = provider
});
复制代码
  • FileExtensionContentTypeProvider类与UseStaticFiles关联使用
  • 扩展名以 "." 开头。
  • 运行结果以下:
    image
  •                                                   
  •                                                                                         
  • 这样入门asp.net core,如何

     

    本文章主要说明asp.net core的建立和简单使用。

    1、使用到的命令

    • dotnet new :建立项目(解决方案,类库,单元测试等),如:dotnet new web
    • dotnet add package 添加一个nuget的引用
    • dotnet test:运行测试
    • dotnet build:编译项目
    • dotnet sln add:将项目添加到解决方案
    • dotnet add reference:对此项目添加项目引用

    2、创建空项目

    • 在测试目录下运行 dotnet new web -n baseWeb,建立web项目,结果以下图所示:
    • image
    • 运行 dotnet run,便可运行此项目,此命令内部会执行dotnet build命令编译项目,而后运行,结果以下:
    • image
      说明:此命令是在sln(解决方案)文件所在目录运行的,因此增长了-p参数,用于指定启动指定的项目。

    3、引入mvc

    • 因为咱们建立是一个空web项目,是没有mvc相关依赖包的,因此首先须要运行dotnet add package Microsoft.AspNet.Mvc 进行依赖包的安装
    • 而后在StartUp类的ConfigureServices方法中添加以下代码:
    public void ConfigureServices(IServiceCollection service){
        service.AddMvc();
        service.AddRouting();
    }

    上述添加此添加了Mvc,也添加了路由

    • 配置路由,仍是在StartUp类中,其方法为Configure添加以下代码:
    复制代码
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        
        //添加的代码
        app.UseMvc(routers=>{
            routers.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
        });
    
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
    复制代码
    • 对controller和view的建立
      在建立controller时,没有找到彻底好的 命令建立方法,因此使用的是手动建立文件,而后继承Controller类实现;而view是能够经过dotnet new page实现的,但也可使用手动建立。文件结果以下:
      image
    • 执行dotnet run运行,而后网页访问对就的地址便可
      image

    4、更换依赖注入为autofac

    aspnet core是自带了依赖注入功能的,就是StartUp类中ConfigureServices方法的IServiceCollection类型的形参。若是你想替换为autofac。请参考以下步骤

    • 安装autofac,以及acutofac的扩展类
      • Autofac
      • Autofac.Extensions.DependencyInjection
    • 更改StartUp类中的configureSeervices方法
    复制代码
    public IServiceProvider ConfigureServices(IServiceCollection service){
        service.AddMvc();
        service.AddRouting();
        var containerBuilder = new ContainerBuilder();
        containerBuilder.Populate(service);
        containerBuilder.RegisterType<Services.ProductService>().As<Services.IProductService>();
        var container = containerBuilder.Build(); 
        return new AutofacServiceProvider(container);
    }
    复制代码
    • 其中,咱们更改了ConfigureServices方法的返回值,由void换成IServiceProvider;此返回为AutofacServiceProvider类的一个实例;在上述过程当中,使用了continerBuilder.Populate方法将service(IServiceCollection的实例对象)注入到autofac中。
    • 其中为了测试DI能力,咱们建立一个IProductService的注入,并在Controller中使用,相关代码以下:
      • IProductService
    复制代码
    namespace baseWeb.Services
    {
        public interface IProductService
        {
            int Get(int id);
        }  
    }
    复制代码
    • ProductService
    复制代码
    using System.Collections.Generic;
    
    namespace baseWeb.Services
    {
        public class ProductService:IProductService
        {
            List<int> ls = new List<int>();
            
            public ProductService(){
                for(var i=0; i<10; i++){
                    ls.Add(i+10);
                }
            }
            public int Get(int id){
                return ls[id];
            }
        }
    }
    复制代码
    • HomeController
    复制代码
    using System;
    using System.Collections.Generic;
    using Microsoft.AspNetCore.Mvc;
    
    namespace baseWeb.Controllers
    {
        public class HomeController:Controller
        {
            private Services.IProductService productService;
    
            public HomeController(Services.IProductService productService){
                this.productService = productService;
            }
    
            public IActionResult Index(int id){
                ViewData["value"] = this.productService.Get(id);
                return View();
            }
        }
    }
    复制代码
    • 运行结果以下:
      image

    5、加入单元测试

    在实际开发中,常常须要用到单元测试。.net core的单元测试也是如此的 so easy, fallow me。

    • 运行dotnet new xunit -n baseWebTest,便可建立一个以xunit为测试框架的单元测试项目
    • 运行dotnet add package Moq,安装Moq模拟框架(此命令须要进入到baseWebTest项目文件夹后运行)
    • 运行dotnet add reference ../baseWeb/baseWeb.csproj,将baseWeb项目引入到此项目中。
    • 编写单元测试代码以下:
    复制代码
    using System;
    using Xunit;
    using Moq;
    using baseWeb.Controllers;
    using baseWeb.Services;
    using Microsoft.AspNetCore.Mvc;
    
    namespace basewebtest
    {
        public class DemoTest
        {
            [Fact]
            public void Test1()
            {
                var productServiceMock = new Mock<IProductService>();
                productServiceMock.Setup(service=>service.Get(1)).Returns((int id)=>{
                    return id+10;
                });
                var _controller = new HomeController(productServiceMock.Object);
    
                var result = _controller.Index(1);
                var objectResult = Assert.IsType<ViewResult>(result);
                var destResult = Assert.IsAssignableFrom<int>(objectResult.ViewData["value"]);
                Assert.Equal(11, destResult);
            }
        }
    }
    复制代码
    • 运行dotnet test -p ./baseWebtest/baseWebtest.csproj便可,看到以下结果:
    • image

    6、其余

    • 若是你是使用vscode编写,那么测试项目是能够在编译器中进行运行和调试的
      image
    • 下载测试源码
相关文章
相关标签/搜索