博客 (58)

新建项目

使用 VS2017 / VS2015 新建项目 - ASP.NET Web 应用程序 - MVC - 个人身份验证

添加模型

右击 Models 文件夹,添加 Movie

using System;
using System.Data.Entity;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}

Movie 类表示一部电影,一个对象实例对应数据库中一行,每个属性对应表中一列。

MovieDBContext 代表 EF 数据库上下文,处理抓取、存储、更新。

创建连接字符串和使用 SQL Server 

打开 Web.config

在 <configuration /> 中的 <connectionStrings /> 中添加

<add name="MovieDBContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Movies.mdf;Initial Catalog=Movies;Integrated Security=True"
      providerName="System.Data.SqlClient" />

name 必须与 DbContext 类的名称匹配(MovieDBContext)

这步将会把数据库文件 Movies.mdf 创建到 App_Data 文件夹中,你也可以使用其它 SQL Server 数据库的连接字符串,简单的方法是:

在“服务器资源管理器”中添加连接

从右击属性中获取连接字符串

从控制器访问模型的数据

右击 Controllers 文件夹添加控制器,选择 包含视图的 MVC 5 控制器(使用 Entity Framework)

模型类:Movie (MvcMovie.Models)

数据上下文类:MovieDBContext (MvcMovie.Models)

F5 运行,访问 /Movies 可添加、查看、编辑、删除影片

添加新字段

设置模型更改的 Code First 迁移

程序包管理器控制台窗口中,在 PM> 提示符下输入

Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext

在 Migrations 文件夹中新建了 Configurations.cs,打开并在 Seed 方法中加入

context.Movies.AddOrUpdate(i => i.Title,
  new Movie
  {
    Title = "When Harry Met Sally",
    ReleaseDate = DateTime.Parse("1989-1-11"),
    Genre = "Romantic Comedy",
    Price = 7.99M
  },
  new Movie
  {
    Title = "Ghostbusters ",
    ReleaseDate = DateTime.Parse("1984-3-13"),
    Genre = "Comedy",
    Price = 8.99M
  }
);

Seed() 将在每次迁移(PM>update-database)后被调用执行,AddOrUpdate 将执行 upsert 操作(有则 update,无则 insert)

AddOrUpdate 的第一个参数指定用于检查行是否已存在的属性

如果该属性值不唯,则出现异常

序列包含多个元素

创建迁移命令:

PM>add-migration Initial

名称“Initial”是任意的

执行迁移:

PM>update-database

F5 运行将显示种子数据

向 Movie 模型添加 Rating 属性

向 Movie 类添加属性,生成

public string Rating { get; set; }

CreateEdit Action 方法的 Bind 属性添加 Rating

更改各视图支持新的 Rating 属性

此时 F5 运行将提示

System.InvalidOperationException:“支持“MovieDBContext”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。”

要解决错误除了手动往数据库中添加 Rating 字段外可以利用 Code First 迁移:

更新 Migrations\Configuration.cs 给每个 Movie 对象添加一个 Rating 字段

PM>add-migration Rating

名称 Rating 是任意的

创建了 DbMigration 的派生类 Rating,可以看到添加新列的代码

PM>update-database

数据库自动完成了对新字段的添加,当然 update-database 也会把种子数据还原。

参考

Getting Started with ASP.NET MVC 5

 

xoyozo 9 年前
4,647

收录了一些个人觉得不错的网页开发插件。

由于插件更新频繁,本页如有错误请指正,也欢迎告知更多功能强大、使用方便的插件。

插件简介备注
框架
jQuery最流行的 JS 框架

下载中文文档英文整合文档中文整合文档浏览器支持来自 css88 的文档

官方建议 IE 6-8 使用 1.12.4

Angular中文版
AngularJS (version 1.x)
一套框架,多种平台同时适用手机与桌面MVC 架构,使得开发现代的单一页面应用程序(SPAs:Single Page Applications)变得更加容易
Vue.js是一套用于构建用户界面的渐进式框架。
Bootstrap中文版简洁、直观、强悍的前端开发框架英文文档v3中文文档v2中文文档视频教程主题和模板
jQuery UI为 jQuery 提供更丰富的功能示例:DatepickerColor AnimationShake Effect
功能
jQuery File UploadjQuery 文件上传英文文档
jQuery Cookie读取、写入和删除 cookie浏览器支持文档
json2.jsjson 操作库已弃用,旧 IE 用 jQuery 的 parseJSON,HTML 5 用 JSON.parse
Lightbox

老牌图片浏览插件

推荐使用更强大的 Viewer.js

 
Swiper中文版最现代的移动触摸滑块(Most Modern Mobile Touch Slider)英文文档中文文档,旧浏览器支持版本:2.x.xSwiper 2 英文文档中文文档
jquery-cropper图片裁剪
FastClick用于消除手机浏览器上触摸事件触发之间的 300 毫秒延迟用法不应用的场景
PACE页面加载进度条文档,IE8+
toastrjQuery 通知文档
Autosize一款小巧的,可自动调整 textarea 高度的独立脚本IE9+
X-editable允许您在页面上创建可编辑元素文档Demo
select2一款提供搜索过滤、自定义样式的下拉框插件
jQuery Tags Input标签输入框
用法
Viewer.js图片浏览插件

GitHub(viewerjs)GitHub(jquery-viewer)

jquery-viewer 是 viewerjs 的 jQuery 插件,即在 jQuery 环境中要同时引用这两个脚本。

PDF.jsA general-purpose, web standards-based platform for parsing and rendering PDFs.
编辑器
UEditor百度在线编辑器GitHub 下载文档ASP.NET 部署教程
日期时间
bootstrap-datepickerBootstrap 日期选择器Online Demo
DateTimePicker日期时间选择 
MultiDatesPicker多日期选择 
FullCalendar日历日程事件工作表IE 9+, jQuery 2.0.0+
TimeTo计时、倒计时 
图表
D3.jsD3.js 是基于数据驱动文档工作方式的一款 JavaScript 函数库,主要用于网页作图、生成互动图形,是最流行的可视化库之一。
Highcharts中文版兼容 IE6+、完美支持移动端、图表类型丰富、方便快捷的 HTML5 交互性图表库文档
ECharts百度图表控件 
AntV来自蚂蚁金服的专业、简单、无限可能的可视化解决方案
G2 - 专业易用的可视化类库
G2-mobile - 移动端高性能可视化类库
G6 - 关系图可视化类库
流程图, 关系图, 可视化规范, 地图, 河流图, 力导图, 网络图, UML图, 业务流程图, 时序图
SyntaxHighlighter功能齐全的代码语法高亮插件(JS) 
动态排名数据可视化

将历史数据排名转化为动态柱状图图表

开源代码,非插件,修改使用

GitHub视频教程EV录屏网页示例视频效果
图标
Font Awesome完美的图标字体IE 8+v3.2.1 支持 IE 7进阶用法(定宽/边框/动画/旋转/叠加)
Glyphicons图标字体作为 Bootstrap 组件
Iconfont阿里巴巴矢量图标库用户可以自定义下载多种格式的 icon,也可将图标转换为字体,便于前端工程师自由调整与调用
UI 框架
WeUI同微信原生视觉体验一致的基础样式库DemoWiki
Apple UI Design Resources苹果用户界面设计资源 
xoyozo 9 年前
14,877

程序设计规范:


  • 【推荐】上传的文件直接保存到文件存储服务(如阿里云 OSS),这样即使被上传了后门 shell,对网站服务器也不会有影响。

  • 否则必须通过文件头来确定文件类型,检查文件十六进制的文件头和文件尾是否合法,并检查文件流中是否包含 php、evel 等字符。

  • 不可直接使用客户端文件名来保存文件,特别是后缀名/扩展名。应生成随机文件名,并通过检验文件头来确定文件类型。必须由程序指定保存目录。

  • 使用 OSS 的应直接上传,不要在 ECS 上临时存放或备份。如必须存放的,应按上述规范操作。


服务器安全设置


CentOS + nginx + PHP:

  • 全站文件取消属性中的“执行”权限(chmod),因为这个“执行”与运行 PHP 无关。而需要上传文件的“目录”需要“执行”权限,原因是需要往该目录创建文件。

  • 仅需要写入的目录或文件设置“写入”权限。如上传图片目录、ThinkPHP 的 Runtime 目录。

  • 凡可写目录或文件均不允许运行 PHP / PY 等 除需要被直接访问的 PHP / PY 文件,其它动态文件均不允许被访问到,在 nginx 的配置文件中添加项,参:https://xoyozo.net/Blog/Details/nginx-location-if,若全站使用统一的入口文件访问,那么设置仅该文件允许运行 PHP 即可。通过 IO 方式被其它文件包含的文件,无需运行 PHP 权限。(“deny all”对 include 起作用,但对 IO 不起作用,因此 Runtime 目录可以继续为 ThinkPHP 提供缓存服务。)这一步非常有用。

  • 使用与 nginx 网站用户不同的用户来部署网站文件,如宝塔面板 PHP 使用 www 用户,那么就使用 root 或其它新用户来上传文件,否则将导致全站目录和文件可写。有条件的建议不同网站使用不同的用户,可防止一个网站被入侵后导致其它网站文件或磁盘上的其它文件被泄露的风险(2022年10月2日从宝塔官方社区获悉,宝塔面板暂不支持使用非 www 用户创建并运行网站)。


Windows Server + IIS + ASP.NET:

  • 配置每个磁盘的安全属性,拒绝“IIS_IUSRS”这个用户组的所有权限。只要设置驱动器即可,子文件夹和文件会自动继承。若运行 .NET Framework 项目,需要设置 C:\Windows\Microsoft.NET\Framework\v*.*.*****\Temporary ASP.NET Files\ 目录可修改写入权限,.NET Core 项目不需要此设置。

  • 为每个网站创建一个新用户,仅隶属于“IIS_IUSRS”。网站根目录安全属性添加该用户,权限选择“读取”。(已测取消“读取与执行”不影响 PHP,“列出文件夹内容”视业务需求开启,建议关闭)。仅需要上传文件的目录或文件设置“修改”、“写入”权限。(修改对应修改文件,写入对应上传文件)

  • IIS 网站中设置“物理路径凭据”以及应用程序池的“标识”。

  • IIS 中设置写入目录的“处理程序映射”无脚本

xoyozo 10 年前
8,374

Angulr(没有字母“a”)是一款收费的 Bootstrap Admin Template,我们选择使用 Angular 版本是因为他提供很好的单页应用程序(Single-page application, SPA)用户体验。

官方演示地址:http://flatfull.com/themes/angulr/angular/

主要目录结构:

┌ angular 
│├ api 
│├ css 
││└ app.min.css应用主样式
│├ fonts  
││└ sourcesanspro应用字体库
│├ img 
│├ js 
││├ app 
│││└ */*.js功能模块控制器
││├ controllers 
│││└ *.js组件控制器
││└ app.angular.js应用主脚本
│├ l10n 
││└ *.js语言配置文件
│├ tpl 
││├ blocks 
│││ └ *.html主框架部件
││└ *.html功能模块页
│└ index.html入口文件
 
└ libs
 ├ angular 
 │└ */*.*Angular 插件
 ├ assets 
 │└ */*.*Angulr 插件
 └ jquery 
  └ */*.*jQuery 插件

app.angular.js 中配置了 app 名称(name)、版本(version)、语言(langs),以及框架文件(tpl/app.html)、默认首页(/app/dashboard)、路由表(state)和插件库引用等信息。

首页配置导航菜单项,在 nav.html 中所有菜单项被包含在 <ul class="nav" /> 中,class 含“hidden-folded padder”的是菜单分区名称(如 Navigation),除了第一个,都被 class 含“line dk”的 li 留白,class 含“nav-sub”的 ul 是二级菜单,<i /> 是 icon,<b /> 是 badge,“font-bold”是加粗,translate 是配置多语言的键值。

Angulr 使用 UI-Router 实现路由。ui-sref 是路由键值,只有在 app.angular.js 的路由表中已配置值,该 ui-sref 才会被解释为 href。

以 Timeline 页为例,ui-sref="app.ui.timeline",route 的 state 中指定读取模板文件为 tpl/ui_timeline.html,且访问 url 为 /timeline,而父路由 appapp.ui 的 url 分别为 /app/ui,所以该页实际访问路径后缀为 #/app/ui/timeline

父路由中一般指定 template: "<div ui-view></div>",如果需要载入动画效果,在该 div 中加入相应的 class 即可(fade-*)。ui-view 作为一个容器,用来承载子路由指向的内容,实现路由嵌套。

目前为止,点击菜单项可准确显示页面内容。但当我们复制地址栏中的网址在新窗口中打开时,如果要将菜单自动展开定位到对应相,只要在 <li /> 标签上加上 ui-sref-active="active" 即可,若该项是子菜单,同时需要展开一级菜单,那么在一级菜单的 <li /> 标签上加上 ng-class="{active:$state.includes('app.ui')}",意思是在路由键中包含 app.ui 即展开此菜单。

如果页面需要引入脚本或样式,在路由的 state 上加上 resolve 参数即可,如果是插件(比如 ngGrid),会调用 MODULE_CONFIG(在 app.angular.js)中配置的该插件的相关脚本和样式。

xoyozo 9 年前
9,043

最理想的部署方式是 ClickOnce,但是证书问题会导致安装时提示:

 

Windows 已保护你的电脑

Windows SmartScreen 筛选器已阻止启动一个未识别的应用。运行此应用可能会导致你的电脑存在安全风险。

 

 

这需要一个从 CA 获取的数字证书(http://www.doc88.com/p-785388554071.html)

 

 

百科:                                 http://baike.baidu.com/view/1390498.htm

ClickOnce 部署教程:            http://www.cnblogs.com/weixing/p/3358740.html

Makecert.exe(证书创建工具): https://msdn.microsoft.com/zh-cn/library/bfsktky3.aspx

如何:为 ClickOnce 应用程序向客户端计算机添加一个受信任的发行者:https://msdn.microsoft.com/zh-cn/library/ms172241.aspx

 

执行命令:makecert -r -n "CN=嗨秒网" -sv himiao.pvk himiao.cer

 

Password: LRQelk0l****************FTtJvufI

 

-r                创建自我签名证书。

-n  name         指定主题的证书名称。 此名称必须符合 X.500 标准。 最简单的方法是在双引号中指定此名称,并加上前缀 CN=;例如,-n "CN=myName"。

-sv  pvkFile     指定主题的 .pvk 私钥文件。 如果该文件不存在,系统将创建一个。

 

 

执行命令:Cert2spc himiao.cer himiao.spc

 

执行命令:pvk2pfx -pvk himiao.pvk -spc himiao.spc -pfx himiao.pfx -pi LRQelk0l****************FTtJvufI –po LRQelk0l****************FTtJvufI –f

 

xoyozo 11 年前
5,956

《Windows Server 2008 R2 Web 服务搭建流程》

前提一、安装完系统后,各分区的权限均设为:
    IIS_IUSRS        完全拒绝(不是什么都不勾,而是勾满右侧的拒绝)
一、创建网站用户,如 netXoyozoWww,密码永不过期,仅隶属于 IIS_IUSRS 组。
二、创建网站根目录 net.xoyozo.www,权限添加用户 netXoyozoWww, 允许“读取和执行”、“列出文件夹内容”、“读取”。
        创建上传目录 upload,用户 netXoyozoWww 的权限再允许“修改”、“写入”。
三、IIS 中添加网站,网站名称如 net.xoyozo.www,指定物理路径,点击连接为,特定用户,测试设置……
        主机名 www.xoyozo.net
四、应用程序池,把 net.xoyozo.www 改成实际需要的 .NET 版本;高级设置,标识,自定义帐户 netXoyozoWww
五、选中网站,日志,更改目录,应用
六、展示网站目录树,选中 upload,处理程序映射,编辑功能权限,取消“脚本”前的勾。
    此操作的结果会在该目录下创建 web.config 文件,切勿删除!尚未研究出被上传文件替换的解决方案。程序应严格控制上传路径,阻止修改或替换 web.config 文件

另:
    查看端口命令:netstat -an
 

xoyozo 12 年前
4,279

前言

  最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关的知识,并整理成这篇博客,如果在阅读的过程中发现不对的地方,欢迎大家指正。

同步编程与异步编程

  通常情况下,我们写的C#代码就是同步的,运行在同一个线程中,从程序的第一行代码到最后一句代码顺序执行。而异步编程的核心是使用多线程,通过让不同的线程执行不同的任务,实现不同代码的并行运行。

前台线程与后台线程

  关于多线程,早在.NET2.0时代,基础类库中就提供了Thread实现。默认情况下,实例化一个Thread创建的是前台线程,只要有前台线程在运行,应用程序的进程就一直处于运行状态,以控制台应用程序为例,在Main方法中实例化一个Thread,这个Main方法就会等待Thread线程执行完毕才退出。而对于后台线程,应用程序将不考虑其是否执行完毕,只要应用程序的主线程和前台线程执行完毕就可以退出,退出后所有的后台线程将被自动终止。来看代码应该更清楚一些:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始");

            //实例化Thread,默认创建前台线程
            Thread t1 = new Thread(DoRun1);
            t1.Start();

            //可以通过修改Thread的IsBackground,将其变为后台线程
            Thread t2 = new Thread(DoRun2) { IsBackground = true };
            t2.Start();

            Console.WriteLine("主线程结束");
        }

        static void DoRun1()
        {
            Thread.Sleep(500);
            Console.WriteLine("这是前台线程调用");
        }

        static void DoRun2()
        {
            Thread.Sleep(1500);
            Console.WriteLine("这是后台线程调用");
        }
    }
}

  运行上面的代码,可以看到DoRun2方法的打印信息“这是后台线程调用”将不会被显示出来,因为应用程序执行完主线程和前台线程后,就自动退出了,所有的后台线程将被自动终止。这里后台线程设置了等待1.5s,假如这个后台线程比前台线程或主线程提前执行完毕,对应的信息“这是后台线程调用”将可以被成功打印出来。

Task

  .NET 4.0推出了新一代的多线程模型Task。async/await特性是与Task紧密相关的,所以在了解async/await前必须充分了解Task的使用。这里将以一个简单的Demo来看一下Task的使用,同时与Thread的创建方式做一下对比。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程启动");
            
            //.NET 4.5引入了Task.Run静态方法来启动一个线程
            Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("Task1启动"); });

            //Task启动的是后台线程,假如要在主线程中等待后台线程执行完毕,可以调用Wait方法
            Task task = Task.Run(() => { Thread.Sleep(500); Console.WriteLine("Task2启动"); });
            task.Wait();
            
            Console.WriteLine("主线程结束");
        }
    }
}

  首先,必须明确一点是Task启动的线程是后台线程,不过可以通过在Main方法中调用task.Wait()方法,使应用程序等待task执行完毕。Task与Thread的一个重要区分点是:Task底层是使用线程池的,而Thread每次实例化都会创建一个新的线程。这里可以通过这段代码做一次验证:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;

namespace TestApp
{
    class Program
    {
        static void DoRun1()
        {
            Console.WriteLine("Thread Id =" + Thread.CurrentThread.ManagedThreadId);
        }

        static void DoRun2()
        {
            Thread.Sleep(50);
            Console.WriteLine("Task调用Thread Id =" + Thread.CurrentThread.ManagedThreadId);
        }

        static void Main(string[] args)
        {
            for (int i = 0; i < 50; i++)
            {
                new Thread(DoRun1).Start();
            }

            for (int i = 0; i < 50; i++)
            {
                Task.Run(() => { DoRun2(); });
            }

            //让应用程序不立即退出
            Console.Read();
        }
    }
}

  运行代码,可以看到DoRun1()方法每次的Thread Id都是不同的,而DoRun2()方法的Thread Id是重复出现的。我们知道线程的创建和销毁是一个开销比较大的操作,Task.Run()每次执行将不会立即创建一个新线程,而是到CLR线程池查看是否有空闲的线程,有的话就取一个线程处理这个请求,处理完请求后再把线程放回线程池,这个线程也不会立即撤销,而是设置为空闲状态,可供线程池再次调度,从而减少开销。

Task<TResult>

  Task<TResult>是Task的泛型版本,这两个之间的最大不同是Task<TResult>可以有一个返回值,看一下代码应该一目了然: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始");

            Task task = Task.Run(() => { Thread.Sleep(1000); return Thread.CurrentThread.ManagedThreadId.ToString(); });
            Console.WriteLine(task.Result);

            Console.WriteLine("主线程结束");
        }
    }
}

  Task<TResult>的实例对象有一个Result属性,当在Main方法中调用task.Result的时候,将等待task执行完毕并得到返回值,这里的效果跟调用task.Wait()是一样的,只是多了一个返回值。

async/await 特性

  经过前面的铺垫,终于迎来了这篇文章的主角async/await,还是先通过代码来感受一下这两个特性的使用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("-------主线程启动-------");
            Task task = GetLengthAsync();
            Console.WriteLine("Main方法做其他事情");
            Console.WriteLine("Task返回的值" + task.Result);
            Console.WriteLine("-------主线程结束-------");
        }

        static async Task GetLengthAsync()
        {
            Console.WriteLine("GetLengthAsync Start");  
            string str = await GetStringAsync();
            Console.WriteLine("GetLengthAsync End");
            return str.Length;
        }

        static Task GetStringAsync()
        {
            return Task.Run(() => { Thread.Sleep(2000); return "finished"; });
        }
    }
}

  首先来看一下async关键字。async用来修饰方法,表明这个方法是异步的,声明的方法的返回类型必须为:void或Task或Task<TResult>。返回类型为Task的异步方法中无需使用return返回值,而返回类型为Task<TResult>的异步方法中必须使用return返回一个TResult的值,如上述Demo中的异步方法返回一个int。而返回类型可为void,则是为了和事件处理程序兼容,比如下面的示例:

public Form1()
{
    InitializeComponent();
    btnDo.Click += Down;
}

public async void Down(object sender, EventArgs e)
{
    btnDo.Enabled = false;
    string str = await Run();
    labText.Text = str;
    btnDo.Enabled = true;
}

public Task Run()
{
    return Task.Run(() => { Thread.Sleep(5000); return DateTime.Now.ToString(); });
}

  再来看一下await关键字。await必须用来修饰Task或Task<TResult>,而且只能出现在已经用async关键字修饰的异步方法中。

  通常情况下,async/await必须成对出现才有意义,假如一个方法声明为async,但却没有使用await关键字,则这个方法在执行的时候就被当作同步方法,这时编译器也会抛出警告提示async修饰的方法中没有使用await,将被作为同步方法使用。了解了关键字async\await的特点后,我们来看一下上述Demo在控制台会输入什么吧。

  

  输出的结果已经很明确地告诉我们整个执行流程了。GetLengthAsync异步方法刚开始是同步执行的,所以"GetLengthAsync Start"字符串会被打印出来,直到遇到第一个await关键字,真正的异步任务GetStringAsync开始执行,await相当于起到一个标记/唤醒点的作用,同时将控制权放回给Main方法,"Main方法做其他事情"字符串会被打印出来。之后由于Main方法需要访问到task.Result,所以就会等待异步方法GetLengthAsync的执行,而GetLengthAsync又等待GetStringAsync的执行,一旦GetStringAsync执行完毕,就会回到await GetStringAsync这个点上执行往下执行,这时"GetLengthAsync End"字符串就会被打印出来。

  当然,我们也可以使用下面的方法完成上面控制台的输出。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("-------主线程启动-------");
            Task task = GetLengthAsync();
            Console.WriteLine("Main方法做其他事情");
            Console.WriteLine("Task返回的值" + task.Result);
            Console.WriteLine("-------主线程结束-------");
        }

        static Task GetLengthAsync()
        {
            Console.WriteLine("GetLengthAsync Start");
            Task task = Task.Run(() => { string str = GetStringAsync().Result; 
                Console.WriteLine("GetLengthAsync End"); 
                return str.Length; });           
            return task;
        }

        static Task GetStringAsync()
        {
            return Task.Run(() => { Thread.Sleep(2000); return "finished"; });
        }
    }
}

  对比两种方法,是不是async\await关键字的原理其实就是通过使用一个线程完成异步调用吗?答案是否定的。async关键字表明可以在方法内部使用await关键字,方法在执行到await前都是同步执行的,运行到await处就会挂起,并返回到Main方法中,直到await标记的Task执行完毕,才唤醒回到await点上,继续向下执行。更深入点的介绍可以查看文章末尾的参考文献。

async/await 实际应用

  微软已经对一些基础类库的方法提供了异步实现,接下来将实现一个例子来介绍一下async/await的实际应用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
using System.Net;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始获取博客园首页字符数量");
            Task task1 = CountCharsAsync("http://www.cnblogs.com");
            Console.WriteLine("开始获取百度首页字符数量");
            Task task2 = CountCharsAsync("http://www.baidu.com");

            Console.WriteLine("Main方法中做其他事情");

            Console.WriteLine("博客园:" + task1.Result);
            Console.WriteLine("百度:" + task2.Result);
        }

        static async Task CountCharsAsync(string url)
        {
            WebClient wc = new WebClient();
            string result = await wc.DownloadStringTaskAsync(new Uri(url));
            return result.Length;
        }
    }
}

参考文献:<IIIustrated C# 2012>     关于async/await的FAQ    《深入理解C#》

t
转自 teroy 10 年前
6,415

推荐:参考此文:如何升级 ASP.NET 项目 MySql.Data 和 Connector/NET 至 8.0.x

-------------------------------------------------------------------------------------------------------

这是 MySQL 官方提供的,用来帮助 .NET 开发者使用 LINQ 来方便操作 MySQL 数据库的解决方案。

我们所需要的软件全部被封装在 MySQL Installer 套件当中,非常方便。

下载后选择“Custom”自定义选择需要安装的产品和功能:

  • MySQL Server - 在本机安装 MySQL 数据库,如果我们直接连接远程数据库则不需要安装

  • MySQL for Visual Studio - 是一款 Visual Studio 插件,用于连接和管理 MySQL 数据库

  • Connector/NET - ADO.NET 托管提供程序


使用也非常方便:

  1. 在“服务资源管理器”中添加连接,更改数据源为“MySQL”。(如果没有该项,重启计算机试试;仍然没有,重新运行 MySQL Installer,选择“Modify ...”,勾选对应 VS 版本的“Visual Studio Integration”和“Entity Framework Designer Integration”)

  2. 项目中“添加新项”,在“数据”中选择“ADO.NET 实体数据模型”,即 Entity Framework,而非“LINQ to SQL 类”,根据需要选择表、视图和存储过程


Windows Server 服务器上安装 MySQL Server 过程中(或安装完成后再次运行 MySQL Installer)可配置端口(同时配置防火墙)。

建议勾选安装 MySQL Workbench 来管理 MySQL 数据库。

新建用户时,主机填“%”即该用户允许远程连接。


如果报以下错误:

不支持直接到存储查询(DbSet、DbQuery、DbSqlQuery)的数据绑定。应使用数据填充 DbSet (例如通过对 DbSet 调用 Load),然后绑定到本地数据。对于 WPF,绑定到 DbSet.Local。对于 WinForms,绑定到 DbSet.Local.ToBindingList()。

记得在绑定时加一个 .ToList() 即可。


如果发布后报以下错误:

找不到请求的 .Net Framework Data Provider。可能没有安装。

那么在服务器上安装 Connector/NET 即可。


如果在 VS 中连接此 EF 时如果遇到:

您的项目引用了最新版的实体框架;但是,找不到进行数据连接所需的与此版本兼容的实体框架数据库提供程序。请退出向导,安装兼容提供程序,重新生成您的项目,然后再执行此操作。

指定的架构无效。错误 0152: 未找到具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序的实体框架提供程序。请确保在应用程序配置文件的“entityFramework”节中注册了该提供程序。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=260882。

那么,只需在 NuGet 中搜索并重新安装 MySql.Data.Entity ,重新生成项目。如果仍然提示,请检查 Connector/NET 是否有更新。 

6.10.4 版本相关的问题参:MySQL Connector/Net 6.10.4 不支持 VS

xoyozo 10 年前
7,319

本文是一个初学者对苹果开发证书的理解,有一定局限性,不适合所有苹果开发者参考,欢迎批评指正。

 

发布 iOS 应用主要有三块内容:Certificates, Identifiers & Profiles

Certificates(证书):是用来给应用程序签名的

Identifiers(标识符):一个应用对应一个 ID,相当于应用程序的身份证

Provisioning Profiles(描述文件):它将证书、标识符、设备结合起来,形成一个描述文件,让 Xcode 知道需要打一个怎么样的 .ipa 包

 

如何创建证书

创建 App ID 就不详说了,不要使用带通配符的名称。值得一提的是,如果要使用推送,必须勾选“Push Notifications”,其它功能按需勾选。

创建证书,需要用到 Mac 电脑上的“钥匙串访问”来生成一个“本地证书”(CSR 文件):

打开“钥匙串访问” - 证书助理 - 从证书颁发机构请求证书 - 保存到磁盘

然后就可以拿这个本地证书去 Apple Developer 里生成“开发证书”或“发布证书”(CER 文件)。打包证书和推送证书生成过程类似,区别是选择“App Store and Ad Hoc”还是“Apple Push Notification service SSL”。下载后添加到钥匙串就完成了。

添加测试设备就不提了。

然后就是描述文件,同样有开发和发布两种。开发主要是用于 Xcode 环境中;发布中还分两种:App Store 是用于正式上线的,Ad Hoc 是用于测试设备的。下一步选择 App ID,下一步选择证书,然后给 Profile 取个能够分辨的名字,生成的是一个 mobileprovision 文件。

 

提供证书文件给第三方打包平台

一般需要提供“iOS Distribution 证书”、“推送证书”、“Ad Hoc”和“App Store”类型的 Profiles、App ID 以及 iTunes Connect 中的 Apple ID(不是指登录的邮箱,是指在 iTunes Connect 中创建的 App 在商店中的 ID)。

证书其实跟 App ID 不是一一对应的关系,多个 App 是可以使用同一个证书的。可以单独创建,到期互不影响。Download 后是 .cer 格式,用“钥匙串”工具可以导出 .p12 证书并设置密码。

如果由于命名无序或创建错误导致无法分辨上架中的 App 用的是哪个证书,哪个描述文件,那么,首先要知道这个 App ID 是多少(就是 iTunes Connect 中所谓的“套装 ID”),然后在 Provisioning Profiles 中挨个查看对应的 App ID,点击“Edit”还能看到使用的证书。

有些平台需要 .pem 文件,是由 .p12 文件通过一个命令转化而来的,具体可以百度。

 

证书过期怎么办

创建一个呗,然后描述文件 Edit,选择新的证书。

 

推送证书过期怎么办

在 App ID 里 Edit 就能查看 Push Notifications 项的 SSL Certificate 是否过期。如果过期需要重新创建证书,可以直接在 App ID 的 Edit 里快捷创建(需要“钥匙串”配合)。

不用重新提交 App Store 审核

 

换一台电脑,证书要怎么导过去

这个问题适用于自己使用 Xcode 开发应用的情况,暂时问一下百度吧。

 

注:本文部分总结来自百度,未经证实。

Apple Push Services 和 APNs Production iOS 这两种类型有什么区别?

xoyozo 10 年前
5,698

“/”应用程序中的服务器错误。


未能加载文件或程序集“XXXXXX”或它的某一个依赖项。试图加载格式不正确的程序。

说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

异常详细信息: System.BadImageFormatException: 未能加载文件或程序集“XXXXXX”或它的某一个依赖项。试图加载格式不正确的程序。

源错误: 
 
执行当前 Web 请求期间生成了未经处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。

程序集加载跟踪: 下列信息有助于确定程序集“XXXXXX”未能加载的原因。
 

警告: 程序集绑定日志记录被关闭。
要启用程序集绑定失败日志记录,请将注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD)设置为 1。
注意: 会有一些与程序集绑定失败日志记录关联的性能损失。
要关闭此功能,请移除注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog]。

当使用 Visual Studio 发布网站时,可能会遇到上述黄屏报错,原因之一是引用的 dll 路径不正确,可以用 Release 模式生成一次看看;原因之二是应用程序的位数与服务器的不匹配。

一般来说用“Any CPU”的方式没有问题,但遇到上述报错的百度网友都很轻松地通过修改 IIS 应用程序池的“启用 32 位应用程序”来解决这个问题,原因是他们的服务器是 64 位操作系统。当我这次在 32 位操作系统的服务器上遇到这个问题的时候真的是手足无措了,然后一阵乱配置,偶尔还能成功跑起来,于是仔细对比了发布到服务器上的文件,发现只有 bin 目录下的 dll 文件有区别,而导致这些区别的原因是我在发布时把“Release - Any CPU”换成了“Debug - Any CPU”,所以一时找不到更好的解决办法的朋友不妨也试试这个方法,只是会有一点点担心性能问题。有更好的解决方案的朋友也不要忘了联系我。

xoyozo 10 年前
8,506