.NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了
作者:依乐祝
原文链接:https://www.cnblogs.com/yilezhu/p/9985451.html
本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core。既然是快速入门所以过多过深的内容我这里就一笔带过了!然后在后面的一些列文章中再慢慢的对其中的概念进行阐述。
本文已收录至.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划 点击可以查看更多教程。
.NET Core是什么
很多朋友看到.NET Core就认为是ASP.NET Core,其实这是有误区的,因为.NET Core 是开放源代码的通用开发平台 (是一个“平台”),基于这个开放平台我们可以开发像ASP.NET Core应用程序, Windows 10 通用 Windows 平台 (UWP),Tizen等等,而我们系列教程就是用.NET Core开发ASP.NET Core应用程序。而且由 Microsoft官方团队 和 .NET社区成员共同在 GitHub 上进行维护。 它跨平台(支持 Windows、macOS 和 Linux),并且可用于生成设备、云和 IoT 应用程序。
.NET Core 还具有以下特性:
- 跨平台: 可以在 Windows、macOS 和 Linux 操作系统上运行。
- 跨体系结构保持一致: 在多个体系结构(包括 x64、x86 和 ARM)上以相同的行为运行代码。
- 命令行工具: 包括用于本地开发和持续集成方案中的易于使用的命令行工具。
- 部署灵活: 可以包含在应用或已安装的并行用户或计算机范围中。 可搭配 Docker 容器使用。
- 兼容性:.NET Core 通过 .NET Standard与 .NET Framework、Xamarin 和 Mono 兼容。
- 开放源:.NET Core 是一个开放源平台,使用 MIT 和 Apache 2 许可证。 .NET Core 是一个 .NET Foundation 项目。
- 由 Microsoft 支持:.NET Core背后依托强大的Microsoft团队 进行维护。
什么是ASP.NET Core
ASP.NET Core 是一个由微软创建的,用于构建 web 应用、API、微服务 的 web 框架。它使用常见的模式,诸如 MVC(Model-View-Controller)、依赖注入,和一个由中间件构成的请求处理管道。它基于 Apache 2.0 许可证开放源码,就是说,源代码可以自由获取,并且欢迎社区成员以 缺陷修复 和 新功能提交 的方式进行贡献。
ASP.NET Core 运行在微软的 .NET 运行时库上,类似于 Java 的 虚拟机(JVM)或者 Ruby 的解释器。有几种语言(C#,Visual Basic,F#)可以用来编写 ASP.NET Core 程序。C# 是最常见的选择,当然我大多数人都是采用C#来进行开发的。你可以在 Windows、Mac,和 Linux 上构建并运行 ASP.NET Core 应用。
为什么要用ASP.NET Core开发应用程序
现存的 web 框架选项已经很多了:Node/Express、Spring、Ruby on Rails、Django、Laravel 等等,数不胜数。ASP.NET Core 又有什么可取之处呢?为什么要用ASP.NET Core开发应用程序呢?
- 速度 ASP.NET Core 很快。因为 .NET Core 是编译运行的,执行速度远高于解释执行的语言,比如 JavaScript 或者 Ruby、ASP.NET Core 也已经为多线程和异步任务作了专门的优化。与使用 Node.js 写的代码相比,执行速度高出 5-10 倍是很正常的。
- 生态 ASP.NET Core 可能初出茅庐,但 .NET 却已久经考验。在 NuGet(.NET 的包管理系统,类似 npm、Ruby gems,或者 Maven)上有成千上万的软件包。有现成的包可用来完成 JSON 反序列化、数据库连接、PDF生成,或者几乎你能想到的任何需求。
- 安全性 微软的开团队很注重安全性,ASP.NET Core 从创建基础就是安全的。它已经自动处理了 净化输入数据 和 跨域伪造请求(CSRF),你就不用操心这些了。你同时还享有 .NET 编译器的静态类型检测的优势,它像个时刻警惕着,还有些强迫症的审校者。这样,在使用一个变量或者某些数据时,那些无意识的错误就插翅难逃。
- 跨平台 可以运行在安装了 .NET 运行时库的 Windows、Mac或者Linux上。
- 开源 .NET Core 属于开放源(MIT 许可证),由 Microsoft 于 2014 年提供给 .NET Foundation。 现在它是最活跃的 .NET Foundation 项目之一。 可由个人和企业自由采用,包括用于个人、学术或商业目的。 同时开源也就意味着在你出现问题的时候你可以阅读其源代码来获取解决问题的方法,再者你也可以在Gayhub上提Issue
数百万开发人员使用过(并将继续使用)ASP.NET 4.x创建 Web 应用。 ASP.NET Core 是重新设计的 ASP.NET 4.x,更改了体系结构,形成了更精简的模块化框架。
ASP.NET Core 同时具有如下优点:
- 生成 Web UI 和 Web API 的统一场景。
- 针对可测试性进行构建。
- Razor Pages可以使基于页面的编码方式更简单高效。
- 能够在 Windows、macOS 和 Linux 上进行开发和运行。
- 开放源代码和以社区为中心。
- 集成新式客户端框架和开发工作流。
- 基于环境的云就绪配置系统。
- 内置依赖项注入。
- 轻型的高性能模块化 HTTP 请求管道。
- 能够在 IIS、Nginx、Apache、Docker上进行托管或在自己的进程中进行自托管。
- 基于 .NET Core运行时,可以使用并行应用版本控制。
……
.NET Core环境搭建
在继续进行ASP.NET Core代码的编写前,我们需要安装 .NET Core的运行环境。这部分我们就一步一步的进行 .NET Core的环境搭建吧。
-
首先你可以Google搜索一下.NET Core,如果没错的话第一个就是微软的官方下载地址,当然你可以点击这里进行下载 (目前sdk最新的是v2.1.500,runtime最新的版本是v2.1.6 )进行开发的话下载SDK即可。
-
双击你下载好的sdk然后傻瓜式的一步一步的进行安装即可,微软的软件的安装太简单的,以至于我如果再细说你们都会嫌我啰嗦了。所以,这里我只贴一张安装成功的图吧。
-
接下来按住
Shift+鼠标右键
,然后选择“在此处打开Powershell窗口”或者“在此处打开命令行窗口”。然后输入dotnet --info
查看下我们已经安装的.NET Core 的信息,当前运行的环境,已经以往安装的版本信息,我的版本比较多,因为我用了很长时间了。如果你第一次安装可能只有一个。出现下面第二张图的界面也就说明我们的.net core开发环境已经就绪了!下面就让我们撸起袖子开始干吧。
快速创建一个ASP.NET Core项目并进行实战演练
这里为了照顾到更多的小伙伴,我就不实用CLI命令行来创建ASP.NET Core项目了,还是中规中矩的使用VS2017吧!什么vs2017需要激活码?那你可以使用社区版的啊!社区版的话,学习已经够用了!废话说了一堆,我们开始吧!
-
首先第一步肯定是打开你的VS2017了,然后点击左上角“文件”-》“新建”-》“项目”(或者你嫌麻烦,可以使用
Ctrl+Shift+N
这个快捷键),打开如下的创建新项目对话框,然后按照如图所示进行选择并点击确定吧(什么?你居然没创建成功?那么我觉得你是在侮辱我了): -
哈哈,上图点击确定后并没有创建成功,而是会弹出下一个对话框,如下所示,他会让你选择目标框架是.NET Core还是.NET Framework;是选择创建一个空的解决方案还是创建一个带有模板的web项目!至于各自的区别,有兴趣的朋友可以每个都创建一下然后对比下各自的区别哦!这里我们按照下图所示选择MVC的web应用程序:
-
创建成功后,看到如下的结构,标准的MVC结构,不过跟.net framework时代的MVC又有所不同。wwwroot:网站的静态文件目录(为什么在这里就能加载呢?大家可以先思考下)
appsettings.json:配置文件,比如数据库连接字符串等等配置信息。
Program.cs:程序入口文件(里面有个Main方法);
Startup.cs启动配置文件 ;
依赖项:管理项目所依赖的第三方组件的安装,配置,升级
Controller:控制器
Models:实体
Views:视图
由于篇幅有限,就不过多的讲解了。
-
按下键盘的F5或者如下图所示点击运行按钮,看下效果吧!
-
如果不出意外的话你将看到如下图所示的界面。
-
看到没有,就这么简单我们就运行起来了一个ASP.NET Core的MVC站点。到这里是不是就已经结束了呢?骚年你想多了,因为我还要让你多会点东西。,所以这个第六条就是用来说废话的,然后作为一个分割。
-
Models:在Models文件夹上右键新建两个类:一个Content类;一个ContentViewModel类 ,代码如下(这里就不教你怎么创建类了,如果跟你说了,那就是在侮辱你的智商了):
namespace Sample01.Models { /// <summary> /// 2018.11.19 /// 祝雷 /// 内容实体 /// </summary> public class Content { /// <summary> /// 主键 /// </summary> public int Id { get; set; } /// <summary> /// 标题 /// </summary> public string title { get; set; } /// <summary> /// 内容 /// </summary> public string content { get; set; } /// <summary> /// 状态 1正常 0删除 /// </summary> public int status { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime add_time { get; set; } /// <summary> /// 修改时间 /// </summary> public DateTime modify_time { get; set; } } }
namespace Sample01.Models { /// <summary> /// 2018.11.19 /// 祝雷 /// Content视图模式 /// </summary> public class ContentViewModel { /// <summary> /// 内容列表 /// </summary> public List<Content> Contents { get; set; } } }
-
Controller:模型建好了,那么我们就新建一个控制器,然后再创建一些模拟的数据吧,代码如下:
namespace Sample01.Controllers { /// <summary> /// 2018.11.19 /// 祝雷 /// Content控制器 /// </summary> public class ContentController : Controller { /// <summary> /// 首页显示 /// </summary> /// <returns></returns> public IActionResult Index() { var contents = new List<Content>(); for (int i = 1; i < 11; i++) { contents.Add(new Content { Id=i,title=$"{i}的标题",content= $"{i}的内容",status=1, add_time=DateTime.Now.AddDays(-i)}); } return View(contents); } } }
-
Views:模型跟控制器都建好了,那我们就建一个视图来显示我们创建的数据吧!我们可以有很多种方式创建这个视图,这里给你介绍一种傻瓜式的,把鼠标放在Index大括号里面,然后鼠标右键选择创建实体,如下所示即可创建视图文件,位置在/Views/Content/Index.cshtml文件:
-
我们按照如下的代码稍微改造下这个View:
@model ContentViewModel @using Humanizer; @{ ViewData["Title"] = "内容列表"; } <div class="panel panel-default todo-panel"> <div class="panel-heading">@ViewData["Title"]</div> <table class="table table-hover"> <thead> <tr> <td> <input type="checkbox" class="done-checkbox"></td> <td>序号</td> <td>标题</td> <td>内容</td> <td>添加时间</td> </tr> </thead> @foreach (var item in Model.Contents) { <tr> <td> <input type="checkbox" class="done-checkbox"> </td> <td>@item.Id</td> <td>@item.title</td> <td>@item.content</td> <td>@item.add_time.Humanize()</td> </tr> } </table> </div>
-
然后修改下布局文件,位于
Views/Shared/_Layout.cshtml
的布局文件里面存放着所有视图的“基础”HTML。其中就包括导航栏,它被显示在每个页面的顶端。为了向导航栏添加新条目,我们需要再这个文件中增加我们的Content乐目,代码如下:<li><a asp-area="" asp-controller="Content" asp-action="Index">Content</a></li>
-
到这里代码基本完成,按下你的F5键,然后导航到Content看下效果吧:
-
这里是真的结束了!
源代码
你以为我会上传源代码?骚年,想什么呢,这么简单,还是自己敲下吧!不要妄图做眼高手低的人哦!
总结
好了,又到了总结时间,本文首先给你讲解了什么是.NET Core?什么又是ASP.NET Core?接着带着你一步一步的配置了.NET Core的开发环境。最后又带着你一步一步的创建了一个ASP.NET Core的mvc项目,同时又通过一个实战教你如何在页面显示一个Content的列表。如果你跟着楼主一点一点的把代码敲起来,然后跑起来了!那么你会发现ASP.NET Core原来这么简单。什么?你觉得简单?那么下一篇文章,博主就带给你一些复杂的概念,什么依赖注入啊,配置文件的加载啊(分析下源码呗)等等!至此,快速入门ASP.NET Core看这篇就够了,圆满结束。
[WPF]为旧版本的应用添加触控支持
之前做WPF开发时曾经遇到这样一个需求:为一个基于 .NET Framework 3.5开发的老旧WPF程序添加触控支持,以便于大屏触控展示。
接手之后发现这是一个大坑。
项目最初的时候完全没考虑过软件架构设计,业务逻辑基本都写在后台代码中,经过两代程序员的开发维护(初代开发者已离职,文档这种东西不存在的),主界面cs代码已经有上万行,各种事件注册的非常杂乱。由于是做给政府部门用的,稳定性很重要,修修补补不断的打补丁,程序已经非常难维护了。
而且不像最新.net框架下的WPF以及UWP开发中,我们有Pointer开头的系列事件可以统一处理鼠标点击和触控。在基于.net框架 4.7以下版本构建的WPF应用里,鼠标点击和触控是独立的,需要分别处理。
这里有一点需要说明:在单点电阻式触控屏(除了ATM机之类的特殊用途,基本要被淘汰掉了)下,系统对单点触控的处理是模拟的鼠标操作,这种情况下即使不处理触控事件,程序也可以正常运行,需要处理触控事件特指的是支持多点触控的电容式触摸屏。
当时我接手的WPF应用之前是完全没有做过触控事件处理的,我粗略的查找统计了一下,需要处理的按钮点击事件大概有上千个,如果手动处理,将是非常难以接受的重复工作,另外修改后的应用程序也必须完整走一遍测试流程,以防带来灾难性BUG。
那么有没有一种简单的方法可以快速处理呢?
我们知道WPF开发中,所有的用户交互事件都是路由事件,其中带有Preview前缀的为隧道路由事件,不带前缀的为冒泡路由事件。其区别是:隧道路由事件由根元素传递到触发事件的元素,而冒泡路由事件传递方向正好相反。那么,尽管程序中需要处理触控事件的地方很多,但是我们都可以在应用顶层元素中通过冒泡路由事件拦截到。是不是可以利用这一点做文章呢?
我的想法是这样的:由于应用已经处理了鼠标交互事件,那我们完全可以将应用的触控事件转发给鼠标交互事件的Handler去处理,这样就避免了我们做机械的重复操作。
具体处理步骤如下:
-
在应用窗口的顶级元素(可视化树的根节点)上添加触控事件处理程序,捕获应用内部触控事件;
this.AddHandler(TouchUpEvent, new RoutedEventHandler(GetTouchUp)); this.AddHandler(TouchDownEvent, new RoutedEventHandler(GetTouchDown));
-
获取引发事件的源控件(原本想通过e.OriginalSource获取,但测试中发现获取的有错误,所以用UIElement类中的InputHitTest方法传入触控点坐标,获取到引发事件的源控件);
TouchEventArgs te = (TouchEventArgs)e; Point p = te.GetTouchPoint(this).Position;//这里是获取触控点相对某个界面元素的坐标 UIElement uiControl = (UIElement)this.InputHitTest(p);
-
触发源控件的鼠标事件(在TouchUp中还同时触发了Button类的Click事件,用于处理按钮的点击事件);
MouseButtonEventArgs args = new MouseButtonEventArgs(Mouse.PrimaryDevice,te.Timestamp,MouseButton.Left); args.RoutedEvent = MouseDownEvent; uiControl.RaiseEvent(args);
完整的事件处理代码如下:
this.AddHandler(TouchUpEvent, new RoutedEventHandler(GetTouchUp));
this.AddHandler(TouchDownEvent, new RoutedEventHandler(GetTouchDown));
private void GetTouchDown(object sender, RoutedEventArgs e) { TouchEventArgs te = (TouchEventArgs)e; Point p = te.GetTouchPoint(this).Position; UIElement uiControl = (UIElement)this.InputHitTest(p); MouseButtonEventArgs args = new MouseButtonEventArgs(Mouse.PrimaryDevice, te.Timestamp, MouseButton.Left); args.RoutedEvent = MouseDownEvent; uiControl.RaiseEvent(args); } private void GetTouchUp(object sender, RoutedEventArgs e) { TouchEventArgs te = (TouchEventArgs)e; Point p = te.GetTouchPoint(this).Position; UIElement uiControl = (UIElement)this.InputHitTest(p); MouseButtonEventArgs args = new MouseButtonEventArgs(Mouse.PrimaryDevice, te.Timestamp, MouseButton.Left); args.RoutedEvent = MouseUpEvent; uiControl.RaiseEvent(args); uiControl.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); }
要说明的一点是,我这里的处理是不完善的,仅仅处理了常见的点击操作。譬如鼠标右键(合理的触控事件应该是长按界面元素一段时间后触发),鼠标移动,滚轮操作都没有做处理,这些也是可以通过类似的方法转换为合适的触控事件触发的。
结尾
今天文章里所述的内容其实已经是很久以前的东西了,我现在的主要工作方向远离WPF开发很久了,突然翻相关的旧文件想起来,所以才有了这篇文章。好记性不如烂笔头,知识不用总有忘的一天,不如写出来贡献给需要的人,谢谢大家!
js css等静态文件版本控制,一处配置多处更新.net版【原创】
日常web开发中,我们修改了js、css等静态资源文件后,如果文件名不变的话,客户端浏览并不会及时获取最新的资源文件,这就很尴尬了
怎么办呢?
1.实习生:让客户清除缓存?,No ,客户是爸爸 不靠谱
2.初级开发:把文件名改了?,可以,但我们产品样式一天更新8百次,怎么办?不方便
<link href="/css/old.css" rel="stylesheet" type="text/css" /> <link href="/css/new.css" rel="stylesheet" type="text/css" /> ... <link href="/css/new800.css" rel="stylesheet" type="text/css" />
3.中级开发:加版本号?,可以,但这个文件,我们有好几个地方用,版本号都加的乱咯? 不方便
<link href="/css/active.css?v=20181120" rel="stylesheet" type="text/css" />
4.中高级开发(小弟不才):自己搞个,一处配置多处更新,.net版 舒服
利用json的键值特性, 此处仅用js,css举例,其他图片等静态资源,都可以使用
一、 新建json文件 CssJsVersion.json
{ //请添加需要刷新的js或css文件 //说明:"键值": "指向文件" //"css/common.css": "css/common_20170223.css" "pc/css/common.css": "pc/css/common.css?v=20170829001", "pc/css/active.css": "pc/css/active.css?v=20180620001", "pc/js/GasgooJS.common.base.js": "pc/js/GasgooJS.common.base.js?v=20170816001", "pc/js/event.js": "pc/js/event.js?v=20180508001", "pc/js/events.js": "pc/js/events.js?v=20180111007", "pc/js/masterpage.js": "pc/js/masterpage.js?v=20170918001", "pc/js/home.js": "pc/js/home.js?v=20171013001", "pc/js/af.js": "pc/js/af.js?v=20180810", "wap/css/common.css": "wap/css/common.css?v=20171222001", "wap/css/active.css": "wap/css/active.css?v=20171228001", "wap/css/css.css": "wap/css/css.css?v=20180813001", "wap/js/events.js": "wap/js/events.js?v=20180517002", "wap/js/event.js": "wap/js/event.js?v=20171222005", "wap/js/applyform.js": "wap/js/applyform.js?v=20171228001", "wap/js/masterpage.js": "wap/js/masterpage.js?v=20170918001", "ticket/css/ticket.css": "ticket/css/ticket.css?v=20180608", "pay/css/css.css": "pay/css/css.css?v=20180831" }
二、 新建类ContentConfig.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Newtonsoft.Json.Linq; using System.IO; using Newtonsoft.Json; /// <summary> /// ContentConfig 的摘要说明 /// </summary> public class ContentConfig { private static bool noCache = true; private static JObject BuildItems() { var json = File.ReadAllText(HttpContext.Current.Server.MapPath("~/Content/Json/CssJsVersion.json")); return JObject.Parse(json); } public static JObject Items { get { if (noCache || _Items == null) { _Items = BuildItems(); } return _Items; } } private static JObject _Items; public static T GetValue<T>(string key) { try { return Items[key].Value<T>(); } catch (Exception) { return Items["erro"].Value<T>(); } } public static String[] GetStringList(string key) { return Items[key].Select(x => x.Value<String>()).ToArray(); } public static String GetString(string key) { return GetValue<String>(key); } public static int GetInt(string key) { return GetValue<int>(key); } public static string GetJsCssVersionUrl(string OldfileName) { string url = Config.RESOURCE_PATH + "/"; try { url += GetString(OldfileName); } catch (Exception)//未找到 OldfileName { url += OldfileName; } return url; } /// <summary> /// 把Json文本转为实体 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="input"></param> /// <returns></returns> public static T FromJSON<T>(string input) { try { return JsonConvert.DeserializeObject<T>(input); } catch (Exception ex) { return default(T); } } }
三、调用
js:
<script src="<%= ContentConfig.GetJsCssVersionUrl("pc/js/home.js") %>"></script>
css:
<link href="<%= ContentConfig.GetJsCssVersionUrl("pc/css/common.css") %>" rel="stylesheet" type="text/css" />
5.高级开发:任何打包工具都可以做到,如webpack,grunt,gulp 牛逼666 正在学习...
后语:
1. 第四个方法是笔者实际中使用的,有什么问题,也可以交流交流(* ̄︶ ̄)
2.方法那样使用,但不限于那样使用,随意发挥
3.
服务器的状态码有?
200代表成功获取。
404代表文件不存在。
301代表永久转向。
302代表暂时转向。
304代表文件为改变,客户端缓存版本还可以继续使用。
400代表非法请求。
401访问被拒绝。
403代表禁止访问。
500服务器内部错误。
503服务器没有应答,如负载过大等。
C#图片处理,缩略图制作
准备参数:图片文件流、文件名
方法:1.先将图片流通过System.Drawing.Image.FromStream方法转成图片对象
2.通过图片对象.GetThumbnailImage方法生成自定义长宽的缩略图。
生成方法:
缩略图生成:
/// <summary> /// 缩略图 /// shidd /// </summary> /// <param name="myStream">文件流</param> /// <param name="serverUrl">文件名</param> /// <returns>字节数组</returns> private byte[] toImage(Stream myStream, string serverUrl) { //生成缩略图 //创建改变后的Stream var stream = new System.IO.MemoryStream(); //取得后缀名 string suffix = serverUrl.Substring(serverUrl.LastIndexOf(".")); //创建一个图像对象取得上传图片对象 System.Drawing.Image myImage = System.Drawing.Image.FromStream(myStream, false); //int percentage= myImage.Height / myImage.Width;//原图片比例 //由上传图片产生一个缩略图(600*400) System.Drawing.Image thumbImage = myImage.GetThumbnailImage(600, 400, null, System.IntPtr.Zero); //保存缩略图到Stream流 thumbImage.Save(stream, this.getImageFormat(suffix)); //关闭缩略图对象 thumbImage.Dispose(); return stream.ToArray(); }
图片格式:
/// <summary> /// 图片格式 /// </summary> /// <param name="suffix">文件后缀</param> /// <returns></returns> private System.Drawing.Imaging.ImageFormat getImageFormat(string suffix) { System.Drawing.Imaging.ImageFormat myFormat; switch (suffix.ToLower()) { case ".bmp": myFormat = System.Drawing.Imaging.ImageFormat.Bmp; break; case ".emf": myFormat = System.Drawing.Imaging.ImageFormat.Emf; break; case ".exif": myFormat = System.Drawing.Imaging.ImageFormat.Exif; break; case ".gif": myFormat = System.Drawing.Imaging.ImageFormat.Gif; break; case ".icon": myFormat = System.Drawing.Imaging.ImageFormat.Icon; break; case ".jpeg": case ".jpg": myFormat = System.Drawing.Imaging.ImageFormat.Jpeg; break; case ".png": myFormat = System.Drawing.Imaging.ImageFormat.Png; break; case ".tiff": myFormat = System.Drawing.Imaging.ImageFormat.Tiff; break; case ".wmf": myFormat = System.Drawing.Imaging.ImageFormat.Wmf; break; default: myFormat = System.Drawing.Imaging.ImageFormat.MemoryBmp; break; } return (myFormat); }
调用:
//调用缩略图方法 bytes = toImage(ms, ServerUrl);
GIF图缩略(注:缩略后图片不能动了,求高手指点)
// <summary> /// 为GIF图片生成缩略图 /// </summary> /// <param name="phyPath">原图片的路径</param> /// <param name="width">缩略图宽</param> /// <param name="height">缩略图高</param> /// <returns></returns> public byte[] GetThumbnail(Stream myStream, int width, int height) { //创建改变后的Stream var stream = new System.IO.MemoryStream(); //创建一个图像对象取得上传图片对象 System.Drawing.Image myImage = System.Drawing.Image.FromStream(myStream, false); System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height); //从Bitmap创建一个System.Drawing.Graphics System.Drawing.Graphics gr = System.Drawing.Graphics.FromImage(bmp); //设置 gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //下面这个也设成高质量 gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; //下面这个设成High gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //把原始图像绘制成上面所设置宽高的缩小图 System.Drawing.Rectangle rectDestination = new System.Drawing.Rectangle(0, 0, width, height); gr.DrawImage(myImage, rectDestination, 0, 0, myImage.Width, myImage.Height, System.Drawing.GraphicsUnit.Pixel); myImage.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); return stream.ToArray(); }
SqlDataReader 结果集 转成 DataTable
/// <summary> /// SqlDataReader 转成 DataTable /// 源需要是结果集 /// </summary> /// <param name="dataReader"></param> /// <returns></returns> private static DataTable ConvertDataReaderToDataTable(SqlDataReader dataReader) { ///定义DataTable DataTable datatable = new DataTable(); try { ///动态添加表的数据列 for (int i = 0; i < dataReader.FieldCount; i++) { DataColumn myDataColumn = new DataColumn(); myDataColumn.DataType = dataReader.GetFieldType(i); myDataColumn.ColumnName = dataReader.GetName(i); datatable.Columns.Add(myDataColumn); } ///添加表的数据 while (dataReader.Read()) { DataRow myDataRow = datatable.NewRow(); for (int i = 0; i < dataReader.FieldCount; i++) { myDataRow[i] = dataReader[i].ToString(); } datatable.Rows.Add(myDataRow); myDataRow = null; } ///关闭数据读取器 dataReader.Close(); return datatable; } catch (Exception ex) { ///抛出类型转换错误 //SystemError.CreateErrorLog(ex.Message); throw new Exception(ex.Message, ex); } }
DataTable转成List集合
解一:
public class ModelConvertHelper<T> where T : new() // 此处一定要加上new() { public static IList<T> ConvertToModel(DataTable dt) { IList<T> ts = new List<T>();// 定义集合 Type type = typeof(T); // 获得此模型的类型 string tempName = ""; foreach (DataRow dr in dt.Rows) { T t = new T(); PropertyInfo[] propertys = t.GetType().GetProperties();// 获得此模型的公共属性 foreach (PropertyInfo pi in propertys) { tempName = pi.Name; if (dt.Columns.Contains(tempName)) { if (!pi.CanWrite) continue; object value = dr[tempName]; if (value != DBNull.Value) pi.SetValue(t, value, null); } } ts.Add(t); } return ts; } }
解二:
/// <summary> /// DataTable 转换为List 集合 /// </summary> /// <typeparam name="TResult">类型</typeparam> /// <param name="dt">DataTable</param> /// <returns></returns> public static List<TResult> ToList<TResult>(DataTable dt) where TResult : class, new() { //创建一个属性的列表 List<PropertyInfo> prlist = new List<PropertyInfo>(); //获取TResult的类型实例 反射的入口 Type t = typeof(TResult); //获得TResult 的所有的Public 属性 并找出TResult属性和DataTable的列名称相同的属性(PropertyInfo) 并加入到属性列表 Array.ForEach<PropertyInfo>(t.GetProperties(), p => { if (dt.Columns.IndexOf(p.Name) != -1) prlist.Add(p); }); //创建返回的集合 List<TResult> oblist = new List<TResult>(); foreach (DataRow row in dt.Rows) { //创建TResult的实例 TResult ob = new TResult(); //找到对应的数据 并赋值 prlist.ForEach(p => { if (row[p.Name] != DBNull.Value) { Type tt = row[p.Name].GetType(); date = tt.Name; } if (date == "DateTime") { // if (p.Name == "WorkingDate" || p.Name == "CreateDate" || p.Name == "RptDate" || p.Name == "UpdateDate") // { // p.SetValue(ob, row[p.Name].ToString(), null); // } // else // { try { p.SetValue(ob, Convert.ToDateTime(row[p.Name]), null); } catch { } //} } else if (date == "Int32") { //if (p.Name == "IsErr" || p.Name == "State" || p.Name == "SourceType") //{ // p.SetValue(ob, row[p.Name].ToString(), null); //} //else //{ try { p.SetValue(ob, Convert.ToInt32(row[p.Name]), null); } catch { } //} } else if (date == "Decimal") { // if (p.Name == "IsErr") // { try { p.SetValue(ob, Convert.ToDecimal(row[p.Name]), null); } catch { } // } // else // { //p.SetValue(ob, row[p.Name].ToString(), null); //} } else { try { p.SetValue(ob, row[p.Name], null); } catch { } } }); //放入到返回的集合中. oblist.Add(ob); } return oblist; }
解二亲测,解一待测!
如何使用linq读取DataTable集合?AsQueryable() 和 AsEnumerable()区别?
一、准备工作
引入linq和data 相关的using命名空间
DataTable dt=new DataTable();//dt的来源可以是多个地方,比如:数据库,Excel等等。我这里使用Excel.
二、获取DataTable的列名及数据类型的方法
有了这个方法就不必考虑来源中的列名和数据类型,这里就可以查找到。
foreach (DataColumn dc in dt.Columns)//获取DataTable中的列名,这里的dt由于是从Excel导入所有列名为:F1,F2,F3,F4... { MessageBox.Show(string.Format("列名:{0} ,数据类型:{1}", dc.ColumnName, dc.DataType)); }
三、进行linq获取操作
这里获取到的东西我们存到一个List里面。
List<string> s = (from a in dt.AsEnumerable()//每次用Linq来操作集合的时候都会用到AsQueryable()和AsEnumerable(),下面我们讲区别 select a.Field<string>("F2")).ToList<string>();//这里的“F2”就是列名 foreach (var item in s) { MessageBox.Show("Test:" + item.ToString());//读取结果显示 }
四、AsQueryable()和AsEnumerable()的区别?
区别就大了 AsEnumerable() 是 LINQ TO OBJECT
AsQueryable 是 LINQ TO SQL