C# json解析时,得到JObject后怎么判断它的某一键值是否存在?_博问_博客园

mikel阅读(2792)

来源: C# json解析时,得到JObject后怎么判断它的某一键值是否存在?_博问_博客园

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.IO;

namespace JsonTest
{
class Program
{
static void Main(string[] args)
{
string str = “{\”3\”:123,body:456,list:{title:’abc’,body:’what’}}”;
JObject jo = JObject.Parse(str);
if (jo.Property(“3”) == null || jo.Property(“3”).ToString() == “”)
{
Console.WriteLine(“键值key不存在!”);
}
bool hasErr = jo.Properties().Any(p => p.Name == “err”)//或是这样
IEnumerable properties = jo.Properties();
foreach (JProperty item in properties)
{
Console.WriteLine(item.Name + “:” + item.Value);
}
Console.ReadKey();
}
}
}
参考:
http://q.cnblogs.com/q/46146/

用Python完成毫秒级抢单,助你秒杀淘宝大单 - 上海小胖 - 博客园

mikel阅读(1041)

Selenium

来源: 用Python完成毫秒级抢单,助你秒杀淘宝大单 – 上海小胖 – 博客园

目录:

  1. 引言
  2. 环境
  3. 需求分析&前期准备
  4. 淘宝购物流程回顾
  5. 秒杀的实现
  6. 代码梳理
  7. 总结

0 引言

年中购物618大狂欢开始了,各大电商又开始了大力度的折扣促销,我们的小胖又给大家谋了一波福利,淘宝APP直接搜索:小胖发福利,每天领取三次粉丝专属现金大红包。

有了现金大红包,如何做到更省钱的剁手呢?今天给大家提供一种思路,用Python实现秒杀订单,借用自动化方式完成最优解。

1 环境

操作系统:Windows

Python版本:3.7.2

2 需求分析&前期准备

2.0 需求分析

我们的目标是秒杀淘宝的订单,这里面有几个关键点,首先需要登录淘宝,其次你需要准备好订单,最后要在指定时间快速提交订单。

登录淘宝,这里就要用到一个爬虫利器Selenium,它是一个自动化测试工具,利用它我们可以驱动浏览器执行特定的动作,如点击、下拉等等操作,所见即所得。另外对于一些 JavaScript 渲染的页面来说,此种抓取方式非常有效。

2.1 Selenium的安装

Selenium 的安装很简单,可采用如下方式。

pip install selenium

Selenium安装好之后,并不能直接使用,它需要与浏览器进行对接。这里拿Chrome浏览器为例。若想使用Selenium成功调用Chrome浏览器完成相应的操作,需要通过ChromeDriver来驱动。

2.2 ChromeDriver的安装

这里是ChromeDriver的官方下载地址。

链接:

https://chromedriver.storage.googleapis.com/index.html

我们在下载之前先来确认下我们使用的Chrome浏览器版本。

在这里插入图片描述

通过ChromeDriver的下载链接,找到与之对应的Chrome浏览器版本,根据你电脑系统的平台类型进行下载。

在这里插入图片描述
在这里插入图片描述

下载完成之后,解压,将其放置在Python安装路径下Scripts文件夹中即可

在这里插入图片描述

上述操作结束后,我们执行如下命令,测试一下

from selenium import webdriver
# 打开Chrome浏览器
browser = webdriver.Chrome()

代码执行后,若成功打开了浏览器,则证明你的ChromeDriver安装的没问题,可以正常愉快地使用Selenium了。

接下来,我们先来回顾下淘宝购物流程。

3 淘宝购物流程回顾

3.1 首先要打开淘宝网站

https://www.taobao.com

换作使用Seleuinm方式,代码如下:

browser.get("https://www.taobao.com")

3.2 我们登录淘宝才能进行下一步操作

在这里插入图片描述
换成Seleuinm方式,代码:

browser.find_element_by_link_text("亲,请登录").click()

这时我们就要就跳到了一个扫码登录的页面,我们用手机进行扫码,登录成功之后进行下一步。

3.3 登录成功之后,我们来打开购物车,链接如下:

https://cart.taobao.com/cart.htm

换成Seleuinm方式,代码:

browser.get("https://cart.taobao.com/cart.htm")

3.4 我们想要全选购物车中的商品,直接点击全选即可

在这里插入图片描述

换成Seleuinm方式,代码:

browser.find_element_by_id("J_SelectAll1").click()

注:若你的购物车商品比较多,又不想全选购买,那就 手动 勾选想要下单的商品。

3.5 勾选好商品后就可以“结算”下单

在这里插入图片描述

换成Seleuinm方式,代码即:

browser.find_element_by_link_text("结 算").click()

3.6 等待提交完订单后才算数

在这里插入图片描述

换成Seleuinm方式,代码即:

browser.find_element_by_link_text('提交订单').click()

3.7 订单成功秒下之后,接下来的付款,慢慢来就好。

在这里插入图片描述

4 秒杀的实现

秒杀的实现,思路也很简单。这里有两个时间点,一是抢购时间,一是当前时间。只需要比较这两个时间点,到了抢购时间立即下单即可。

记录时间,需要使用datetime这个内置模块,代码如下:

import datetime
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')

5 代码梳理

首先得登录淘宝,这里我们定义一个login函数

def login():
    # 打开淘宝首页,通过扫码登录
    browser.get("https://www.taobao.com")
    time.sleep(3)
    if browser.find_element_by_link_text("亲,请登录"):
        browser.find_element_by_link_text("亲,请登录").click()
        print(f"请尽快扫码登录")
        time.sleep(10)

接下来就是勾选购物车中的商品,这里我们定义一个picking函数

def picking(method):
    # 打开购物车列表页面
    browser.get("https://cart.taobao.com/cart.htm")
    time.sleep(3)


    # 是否全选购物车
    if method == 0:
        while True:
            try:
                if browser.find_element_by_id("J_SelectAll1"):
                    browser.find_element_by_id("J_SelectAll1").click()
                    break
            except:
                print(f"找不到购买按钮")
    else:
        print(f"请手动勾选需要购买的商品")
        time.sleep(5)

等待抢购时间,定时秒杀,这里我们定义一个buy函数

def buy(times):
    while True:
        now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
        # 对比时间,时间到的话就点击结算
        if now > times:
            # 点击结算按钮
            while True:
                try:
                    if browser.find_element_by_link_text("结 算"):
                        browser.find_element_by_link_text("结 算").click()
                        print(f"结算成功,准备提交订单")
                        break
                except:
                    pass
            # 点击提交订单按钮
            while True:
                try:
                    if browser.find_element_by_link_text('提交订单'):
                        browser.find_element_by_link_text('提交订单').click()
                        print(f"抢购成功,请尽快付款")
                except:
                    print(f"再次尝试提交订单")
            time.sleep(0.01)

6 总结

短短几十行代码就能秒杀淘宝订单,赶紧行动起来吧!记着,每天在淘宝上搜索小胖发福利,领取粉专属福利哟~

关注公众号「Python专栏」,后台回复「抢单器」获取全套代码!

Linux下MySql出现#1036 – Table ‘ ‘ is read only 错误解决方法 - 独行客 - 博客园

mikel阅读(1053)

来源: Linux下MySql出现#1036 – Table ‘ ‘ is read only 错误解决方法 – 独行客 – 博客园

这两天在进行网站搬家,这次网站搬家采用直接打包mySQL数据库和网页文件的形式进行迁移,上传好mySQL data目录里面的网站数据库至VPS上mysql存放数据库的目录里面,解压就行。我的VPS存放数据库的路径是 /usr/local/mysql/var。

上传好网站数据,解压,配置好数据库链接参数就行,网站就能正常连接上了,我本以为这已 经是顺利迁移完成了,但后来操作的时候,发现只能读取数据库的内容,不能更改写入任何信息,提示#1036 – Table ‘* ‘ is read only (*号为任意表),也就是说表只有只读属性。

通过SSH,给数据库文件777权限,admin是我的数据库文件夹

1、chmod -R 0777 /usr/local/mysql/var/admin/

给数据库目录的所属用户和组改为MySQL

2、 chown -R mysql:mysql admin

但是这样还不能更改数据库,首先,找到mysqladmin所在位置,一般都在mysql/bin下面,我的在/usr/local/mysql/bin 里面,还需要运行以下命令:

3、./mysqladmin -u root -p flush-tables

之后输入root账号的密码,马上就好了,没有任何任何提示,然后测试一下,能正常读写,搬家也就顺利完成。

SpringBoot 第一篇:入门篇 - 追梦1819 - 博客园

mikel阅读(1813)

来源: SpringBoot 第一篇:入门篇 – 追梦1819 – 博客园

前言

博主从去年开始,项目中使用的框架逐渐被 SpringBoot 取代。今年独立负责的两个项目也都是用 SpringBoot ,看过不少资料、博客。网上的资源,内容有长有短,参差不齐。有的内容甚至存在误导性,误导读者从另一个坑跳进另一个坑。另外,在项目中使用的 SpringBoot 的功能比较零散。

基于此,想系统整理其相关的知识点以及项目中踩得坑,并记录。一是作为自己的一个成长笔记,一是提醒后来的新人绕过已经踩过的坑。

此为本系列博客的写作初心。

概念

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。

springboot 不是一门新技术。它是一个简化Spring应用开发的一个框架,整个Spring技术栈的一个大整合,更提供了J2EE开发的一站式解决方案。

博主更愿意把它理解为一个技术平台(不知道这样理解是否合适,欢迎大佬拍砖),几乎把所有的Java主流技术都整合进去,让开发者“随用随取”,不会陷入到繁杂的配置文件中无法自拔。

优点

  1. 自动化配置(springboot的核心特性);
  2. 简化spring的配置,无需xml配置文件;
  3. 内嵌了Tomcat、Jetty等容器;
  4. 直接运行jar包;

    ……

核心

spring 应用程序开发中,有四个核心:

  • 自动配置:针对很多Spring应用程序常见的应用功能,Spring Boot能自动提供相关配置
  • 起步依赖:告诉Spring Boot需要什么功能,它就能引入需要的库。
  • 命令行界面:这是Spring Boot的可选特性,借此你只需写代码就能完成完整的应用程序,无需传统项目构建。
  • Actuator:让你能够深入运行中的Spring Boot应用程序,一套究竟。

由于篇幅所限,此处先接触一下基本概念,不做深入讲解。后续会一一展开。

快速构建项目

maven构建项目

  1. 进入SpringBoot 项目构建网站 https://start.spring.io/ (如下);

  1. 选择对应的工具、语言、版本、相关信息、依赖等,按住 alt + Enter 下载,然后解压,导入IDE。

IDEA 构建项目

个人推荐使用 idea 构建, 方便,简洁,“傻瓜式”构建,直接 下一步 即可。感兴趣的可以参照之前的博客:https://www.cnblogs.com/yanfei1819/p/7798499.html

项目结构说明

如上图所示,Spring Boot项目的基础结构共三个文件:

  • src/main/java 程序开发以及主程序入口
  • src/main/resources 配置文件
  • src/test/java 测试程序
  • DemoApplication 类是程序入口
  • application.properties 是程序配置文件

在引入web模块后,src/main/resources/static 是静态资源文件放置路径;src/main/resources/template 是使用模板引擎时放置的 .html 静态页面。还有其他的一些路径,后续会一一阐述。

程序启动

程序员的入门课一般都是 Hello Word! ,下面我们演示 SpringBoot 版的 Hello Word! 。

创建controller层:

package com.yanfei1819.demo.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by 追梦1819 on 2019-05-06.
 */
@Controller
public class HelloWordController {
    @ResponseBody
    @GetMapping("/helloWord") // <===> @RequestMapping(value = "/helloWord",method = RequestMethod.GET)
    public String helloWord(){
        return "Hello Word,SpringBoot!";
    }
}

注意两点:

  1. @GetMapping("/helloWord") 等价于 @RequestMapping(value = "/helloWord",method = RequestMethod.GET)
  2. 加上 @ResponseBody 后,返回结果不会被解析为跳转路径,而是直接写入返回值中。如果不加,则会解析为跳转路径;
  3. 程序默认的端口号是 8080,可以通过 application.properties 配置文件的 server.port= 进行修改。

以上程序通过 postman 测试结果是:

总结

SpringBoot 涉及的内容很多,如果没有一个系统的主线去学习,会感觉很零散。以上内容作为本系列博客的入门篇。后续会将 SpringBoot 的功能点一一展开。

本文同步于公众号【技术和人生】,欢迎关注。

.NETCore 快速开发做一个简易商城 - nicye - 博客园

mikel阅读(1386)

来源: .NETCore 快速开发做一个简易商城 – nicye – 博客园

.NETCore 快速开发做一个简易商城

介绍

上一篇介绍 《.NETCore 基于 dbfirst 体验快速开发项目》,讲得不太清楚有些多人没看懂。这次吸取教训,将一个简易商城做为案例,现实快速开发。

本案例用于演示或学习,不具有商业价值。

必备环境

1、node、node、node,重要的说三遍,现代开发必备环境之一,安装文件大小不过十几兆。

2、dotnet-SDK 2.1 +

3、SQLServer 2005 +,或者 SQLServer express

4、genms 命令,安装方法:dotnet tool install genms -g

特别说明 genms

genms 是一个开源的,依据SQLServer数据库快速开发生成工具。

生成原则基于ado.net包装,完成每种数据类型挖掘、数据缓存自动管理、链式查询语法、高可用读写分离等繁琐工作。

设计数据库模型

这次我们选择 SQLserver 存储数据,使用【Microsoft SQL Server Manaement Studio】自带的【数据库关系图】建表,建好表如下:

选择工作目录

由于是demo学习项目,我们选择在桌面创建目录【genms_shop】,在文件窗口地址栏输入cmd回车,如下图。

使用 genms 首次生成完整的项目

假设我们的 SQLserver 服务器就在本地,那么使用如下命令:

genms –help

genms . -D shop -N es -R -A -S

很快就生成好了,genms 准备执行开发环境初始化,如果首次执行 npm install -g gulp-cli 可能有些慢,如图:

如无意外会自动运行该项目,打开浏览器访问 http://localhost:5000/ 如图:

预览运行项目

这是 genms 生成的后台管理系统,现实繁琐的增删查改,我们尝试增加【分类】数据体验下操作,如图:

添加几次数据后,回到 Category 首页查看如图:

再来看看 goods 页面,和添加一个 goods:

总结

在当今,面向 dbfirst 开发的思想比较”落后“,许多同行在对比他们的同时,却忽略了什么是结果导向。技术都是实现业务的工具,不管是 code first 还是 dbfirst 都是为解决业务而存在。

genms 可以快速更新生成的代码,现实了缓存、读写分离(故障无感知切换)等等优势,这个开发模式我已经使用了很多年,并且会一直坚持下去。

本文demo源码:https://github.com/2881099/genms_shop

开源地址:https://github.com/2881099/dotnetgen_sqlserver

感谢支持开源的你们,谢谢观赏!!

如何用机器人监听老板微信? - 猪哥66 - 博客园

mikel阅读(1093)

来源: 如何用机器人监听老板微信? – 猪哥66 – 博客园

随着微信社交的兴起,我们加入的群也越来越多,一个不经意就被拉入好几个群,群是大家协同交流的平台,但是微信群却越来越泛滥,不知道大家有没有统计过自己浪费在毫无营养的群中的时间?
群聊
因为群质量或者群太吵的原因我们往往会将群设置为勿扰模式,而这样又有可能会错过一些自己比较关注的人说的话,比如女神、老板、和产品狗。。。

为了解决这个痛点,猪哥今天带大家一起来看看如何用python开发一个可以监听老板群聊的机器人

一、需求分析

1.女神在聊什么

你可以暗恋公司的某个妹子已久,她的人缘很好常常会在公司群里和大家聊天,所以你一直关注着希望能投其所好,或者产生共鸣,但是作为程序员的你却每天忙成狗,该怎么办?

2.老板有什么指示

在公司大群里,也许老板今天心情买了一些水果犒劳大家,然后在群里说:前台有水果,结果等你看到群消息时,前台只剩下妹子了。为什么吃零食总没有你的份?

3.又要改需求

你好不容易实现了一个功能,结果产品验收不通过,它说已经在项目群里和你说了并且@了你,但是你沉醉于实现功能忘了看。看来今晚又得加班改需求了,心好累怎么办?
改需求

二、功能设计

鉴于上面的需求分析,我们来设计一下功能:我们希望在某些群中监听某些人的讲话,如果他说话了不管发了什么,然后都记录下来,最好是能发到微信上这样更方便查看。

三、功能实现

上期为大家详细介绍了如何用Python创建一个微信机器人与好友聊天功能,今天我们会用wxpy库来一些群功能吧!

1.接收群消息

上次我们实现使用机器人与好友聊天只是实现了接收好友消息,那如何接收群消息呢?请看下图
在这里插入图片描述
这样我们就接收到群消息了,也可以将机器人引入到群中,让大家调戏。

2.过滤有用群消息

能接收到群消息之后,我们如何过滤我们需要的消息呢?这里我们可以在接收到群消息后比较下这个群是不是我们需要监听的群,然后再比较当前消息发送者在不在我们要监听的对象中,如果两者都满足便实现了消息过滤。

在配置文件中指定需要监听人的名称(最好是备注名,防止微信昵称重名)和需要监听的群
在这里插入图片描述
根据配置需要监听的群和人去过滤群消息
在这里插入图片描述

3.转发有用群消息

在我们拿到有用群消息后,我们如何保存这些信息呢?有很多种保存信息的方式,你可以存文件,存数据库,也可以选择转发。这里猪哥就选择将信息转发,这样有几个优点:简单、实时、永久保存。

那转发给谁?你可以转发到指定好友或者文件助手都行,在猪哥的代码中是转发到机器人管理员那里,如果你没有设置管理员那么就转发到文件助手中。
在这里插入图片描述
管理员设置技巧:如果你用小号登录,那么你可以设置你的大号为管理员;如果你没有小号用自己的大号登录,那这个你就空着默认就设置文件助手为管理员,相关信息发送至你的文件助手中。

四、功能演示

监听模式演示

五、总结

目前微信机器人第二阶段开发完成,本次不仅仅新增监听模式,还新增了以下以下一些功能:

  1. 机器人群聊:让机器人加入群聊,让更多的人来撩~
  2. 转发模式:可将老板重要指示转发至其他群
  3. 监控模式:监控群中别人发的分享,这样就可以第一时间发现是否有人在群中发广告
  4. 管理员:指定管理员后可以远程控制机器人的各个开关

大家可以根据自己的日常需求来自由发挥,个性化机器人哦~

Github项目地址:https://github.com/pig6/wxrobot
wxpy官方文档:https://wxpy.readthedocs.io/zh/latest

代码下载后可以直接运行,不需要修改,最后再送大家一张wxpy速查表!
在这里插入图片描述

C#中的@符号的使用 - 晓菜鸟 - 博客园

mikel阅读(1015)

来源: C#中的@符号的使用 – 晓菜鸟 – 博客园

一 字符串中的用法

字符@表示,其后的字符串是个“逐字字符串”(verbatim string)。

@只能对字符串常量作用。

1.用于文件路径

string s_FilePath =”C:\\Program Files\\Microsoft.NET\\test.txt”;

相当于

string s_FilePath =@”C:\Program Files\Microsoft.NET\test.txt”;

@是取消字符串中的转意符。比如不加@的字符串,”\\a\n”C#会解释成一个\和一个a再加一个换行,如果加了@,@”\\a\n“ C#会解释成两个\加一个a加一个\加一个n。

2.用@表示的字符串能够跨越数行。用于在CS中写JS或SQL代码比较方便。

string s_MultiRows = @”Line1

Line2

Line3″;

string s_JavaScript = @”
<script type=””type/JavaScript””>
function doSomething()
{
}
</script>”;

 

 

二 标识符中的用法

在 C#  规范中, @  可以作为标识符(类名、变量名、方法名等)的第一个字符,以允许C# 中保留关键字作为自己定义的标识符。

class @class
{
public static void @static(bool @bool) {
if (@bool)
System.Console.WriteLine(“true”);
else
System.Console.WriteLine(“false”);
}
}
class Class1
{
static void M() {
clu0061ss.stu0061tic(true);
}
}

注意,@ 虽然出现在标识符中,但不作为标识符本身的一部分。
因此,以上示例,定义了一个名为 class 的类,并包含一个名为 static 的方法,以及一个参数名为了 bool 的形参。

这样,对于跨语言的移植带来了便利。因为,某个单词在 C#  中作为保留关键字,但是在其他语言中也许不是。

C#使用log4net记录日志 - 水墨晨诗 - 博客园

mikel阅读(1182)

来源: C#使用log4net记录日志 – 水墨晨诗 – 博客园

一、下载log4net.dll(百度云里面有)文件,然后再在项目中添加引用。

二、在AssemblyInfo.cs文件中添加log4net.dll的参数。

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", ConfigFileExtension = "config", Watch = true)]

 

三、右击项目→添加→新建项→xxx配置文件(web或者winform……)并修改名字叫:log4net.config→右击生成出来的log4net.config→属性→将 “复制到输出目录” 的值改为 如果较新则复制。

在configuration节点下添加下面这段

 

复制代码
<log4net>
  <!--错误日志类-->
  <logger name="logerror"><!--日志类的名字-->
    <level value="ALL" /><!--定义记录的日志级别-->
    <appender-ref ref="ErrorAppender" /><!--记录到哪个介质中去-->
  </logger>
  <!--信息日志类-->
  <logger name="loginfo">
    <level value="ALL" />
    <appender-ref ref="InfoAppender" />
  </logger>
  <!--错误日志附加介质-->
  <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"><!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质-->
    <param name="File" value="Log\\LogError\\" /><!--日志输出到exe程序这个相对目录下-->
    <param name="AppendToFile" value="true" /><!--输出的日志不会覆盖以前的信息-->
    <param name="MaxSizeRollBackups" value="100" /><!--备份文件的个数-->
    <param name="MaxFileSize" value="10240" /><!--当个日志文件的最大大小-->
    <param name="StaticLogFileName" value="false" /><!--是否使用静态文件名-->
    <param name="DatePattern" value="yyyyMMdd&quot;.htm&quot;" /><!--日志文件名-->
    <param name="RollingStyle" value="Date" /><!--文件创建的方式,这里是以Date方式创建-->
    <!--错误日志布局-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="&lt;HR COLOR=red&gt;%n异常时间:%d [%t] &lt;BR&gt;%n异常级别:%-5p &lt;BR&gt;%n异 常 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;"  />
    </layout>
  </appender>
  <!--信息日志附加介质-->
  <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="Log\\LogInfo\\" />
    <param name="AppendToFile" value="true" />
    <param name="MaxFileSize" value="10240" />
    <param name="MaxSizeRollBackups" value="100" />
    <param name="StaticLogFileName" value="false" />
    <param name="DatePattern" value="yyyyMMdd&quot;.htm&quot;" />
    <param name="RollingStyle" value="Date" />
    <!--信息日志布局-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="&lt;HR COLOR=blue&gt;%n日志时间:%d [%t] &lt;BR&gt;%n日志级别:%-5p &lt;BR&gt;%n日 志 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;"  />
    </layout>
  </appender>
</log4net>
复制代码

 

下面是其他的一些配置

 

复制代码
//这种配置,是将日志写入到文本文件当中,若是需要将日志已其他形式保存,可以看 http://www.cnblogs.com/qianlifeng/archive/2011/04/22/2024856.html
        
<param name="File" value="Logger/"/>//日志存放位置(这里的value值是一个Logger,表示在项目文件夹中创建一个名叫Logger的文件。也可以是value="c:\log.txt")
<param name="AppendToFile" value="true"/>//是否追加到文件
<param name="RollingStyle" value="Date"/>//变换的形式为日期
<param name="DatePattern" value="&quot;Logs_&quot;yyyyMMdd&quot;.txt&quot;"/>//生成格式;每天生成一个日志
<param name="StaticLogFileName" value="false"/>//日志文件名,是否固定不变
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>//这3行表示日志输出的格式,若不喜欢这样的样式,可以查看下面的输出样式,自行修改
<param name="Header" value="&#xA;----------------------header--------------------------&#xA;"/>
<param name="Footer" value="&#xA;----------------------footer--------------------------&#xA;"/>
复制代码

输出样式:

%m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息
%n(new line):换行
%d(datetime):输出当前语句运行的时刻
%r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数
%t(thread id):当前语句所在的线程ID
%p(priority): 日志的当前优先级别,即Debug、INFO、WARN…等
%c(class):当前日志对象的名称,例如:
%f(file):输出语句所在的文件名。
%l(line):输出语句所在的行号。
%数字:表示该项的最小长度,如果不够,则用空格填充,如“%-5level”表示level的最小宽度是5个字符,如果实际长度不够5个字符则以空格填充。

通过这些东西,你可以任意组合你喜欢的输出格式内容。

四、使用log4net记录日志

1添加一个帮助类LogHelper

复制代码
    public class LogHelper
    {
        public static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo");
        public static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror");
        public static void WriteLog(string info)
        {
            if (loginfo.IsInfoEnabled)
            {
                loginfo.Info(info);
            }
        }

        public static void WriteLog(string info, Exception ex)
        {
            if (logerror.IsErrorEnabled)
            {
                logerror.Error(info, ex);
            }
        }
    }
复制代码

2、在代码中记录错误

复制代码
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                string a = "FF";
                int b = Convert.ToInt32(a);
            }
            catch (Exception ex){
                LogHelper.WriteLog(ex.Message.ToString(), ex);
            }
        }
复制代码

 

如何是在web中,可以创建global.asax页面,

右击项目→添加→新建项目→选择web中的全局应用程序类。

在global.asax.cs文件中,找到application_error方法中,增加写入错误日志的代码。

Exception ex = Server.GetLastError().GetBaseException(); //获取异常源 
然后使用上面的方法记录就可以了

如果项目使用的框架是 client profile版本的是不能使用log4net的,请将框架修改相对应的完整版的  项目→XXX属性→修改目标框架。

参考:https://www.cnblogs.com/xuxuzhaozhao/p/6640623.html

一个项目引用不同版本dll - 养家心法 - CSDN博客

mikel阅读(1527)

来源: 一个项目引用不同版本dll – 养家心法 – CSDN博客

问题描述

一个项目引用不同版本的同一dll,会引发以下报错:

未能加载文件或程序集“xxx, Version=x.x.x.x, Culture=neutral, PublicKeyToken=xxxxxxxxxxxx”或它的某一个依赖项。系统找不到指定的文件

这里来解决项目中同一dll的多版本问题。

解决方式

通过配置web.config配置文件(app.config或web.config)增加配置节点

不同场景有不同的解决方式,下面说明

1. 场景一   以高版本兼容

例如:新旧项目都引用Newtonsoft.Json,但是不同版本。需要以最高版本兼容。

  1. <runtime>
  2.   <assemblyBinding xmlns=“urn:schemas-microsoft-com:asm.v1”>
  3.     <dependentAssembly>
  4.       <assemblyIdentity name=“Newtonsoft.Json” publicKeyToken=“30AD4FE6B2A6AEED” culture=“neutral”/>
  5.       <bindingRedirect oldVersion=“0.0.0.0-6.0.0.0” newVersion=“6.0.0.0”/>
  6.     </dependentAssembly>
  7.   </assemblyBinding>
  8. </runtime>

 

2. 场景二   同一dll两种版本共存

例如:项目自己引用log4net.dll 版本1.2.13.0 。添加第三方某个dll,第三方依赖log4net.dll版本1.2.9.0,项目中需要两种版本共存。
这里还分两种情况,dll的publicKeyToken相同还是不同 (publicKeyToken查询见说明1)
publicKeyToken相同,配置方法:
  1. <runtime>
  2.   <assemblyBinding xmlns=“urn:schemas-microsoft-com:asm.v1”>
  3.     <dependentAssembly>
  4.       <assemblyIdentity name=“log4net” publicKeyToken=“669e0ddf0bb1aa2a” />
  5.       <codeBase version=“1.2.13.0” href=“bin\log4netdll\1_2_13\log4net.dll” />
  6.       <codeBase version=“1.2.9.0” href=“bin\log4netdll\1_2_9\log4net.dll” />
  7.     </dependentAssembly>
  8.   </assemblyBinding>
  9. </runtime>

publicKeyToken不同,配置方法:

  1. <runtime>
  2.   <assemblyBinding xmlns=“urn:schemas-microsoft-com:asm.v1”>
  3.     <dependentAssembly>
  4.       <assemblyIdentity name=“log4net” publicKeyToken=“669e0ddf0bb1aa2a” />
  5.       <codeBase version=“1.2.13.0” href=“bin\log4netdll\1_2_13\log4net.dll” />
  6.     </dependentAssembly>
  7.     <dependentAssembly>
  8.       <assemblyIdentity name=“log4net” publicKeyToken=“b32731d11ce58905” />
  9.       <codeBase version=“1.2.9.0” href=“bin\log4netdll\1_2_9\log4net.dll” />
  10.     </dependentAssembly>
  11.   </assemblyBinding>
  12. </runtime>

说明

1.publicKeyToken获取方式:使用vs的Tools Command Prompt命令行工具,输入:SN -T “path”,例如:

  1. C:\Program Files (x86)\Microsoft Visual Studio 11.0>SN -T “D:\project\liberary\External\log4net.dll”
  2. Microsoft(R) .NET Framework 强名称实用工具 版本 4.0.30319.17929
  3. 版权所有(C) Microsoft Corporation。保留所有权利。
  4. 公钥标记为 b32731d11ce58905

注意:href的路径要保证正确。

参考文献

msdn对配置详解:  点击打开链接

参考文章

http://blog.csdn.net/dang13579/article/details/72956684

Asp.Net MVC 中的 Cookie(译) - JoeSnail - 博客园

mikel阅读(653)

来源: Asp.Net MVC 中的 Cookie(译) – JoeSnail – 博客园

  • Cookie是请求服务器或访问Web页面时携带的一个小的文本信息。

Cookie为Web应用程序中提供了一种存储特定用户信息的方法。Cookie的值是字符串类型,且对用户是可见的。

  • Cookie随着每次RequestResponse在浏览器和服务器之间交换数据。

如果一个用户请求服务器上的一个页面,服务器除了返回请求的页面,也返回了一个包含日期和时间的Cookie。这个Cookie存储在用户硬盘上的一个文件夹上。稍后,如果用户再次访问服务器,当用户输入URL时,浏览器会在本地硬盘上查看与该URL相关联的Cookie。如果Cookie存在,浏览器会将Cookie随着请求一起发送。然后,服务器可以读取发送过来的Cookie信息,用户上次访问该站点的日期和时间。您可以使用这些信息向用户显示一条消息,或者检查一个过期日期。

  • Cookie与特定的站点关联

Cookie与一个Web站点相关联,而不是特定的页面,因此不管用户请求你服务器的什么页面,浏览器和服务器都会交换cookie信息。 浏览器会为每个不同的Web站点分别存储Cookie,保证每个Cookie对应特定的Web站点。

  • Cookie保持会话状态

Cookie可以帮助服务器存储访问者的信息。通俗的说,Cookie是保持Web应用程序连续性的一种方式,即会话状态管理。因为Http请求是无状态的,一些列请求中服务器并不知道请求来自哪些用户,所以可以使用Cookie来唯一标识用户,维护会话状态。

Cookie用于许多目的,所有这些都与帮助网站记住用户有关。例如,一个进行投票的站点可能会使用Cookie作为布尔值来指示用户的浏览器是否已经参与投票,这样用户就不能进行两次投票。一个要求用户登录的网站可能会使用Cookie来记录用户已经登录的情况,这样用户就不必继续输入凭证了。


Cookie限制

大多数浏览器支持最多4096字节的Cookie。由于这个限制,cookie最好用于存储少量数据,或者更好的是,像用户ID这样的标识符。

浏览器也会限制Web网站在用户的电脑上可以存储多少Cookie。大多数浏览器只允许每个站点提供20个Cookie。如果你想储存更多,那么之前老的Cookie就会被丢弃。一些浏览器还会限制Cookie的总数量(不区分站点)。

尽管Cookie对Web应用程序非常有用,但是应用程序不应该依赖于Cookie。不要使用Cookie来支持关键敏感数据。


写Cookie

浏览器负责管理用户电脑上的Cookie。Cookie通过HttpResonse对象被发送到浏览器,该对象公开了一个名为Cookies的集合。想要发送到浏览器的任何Cookie都必须添加到这个集合中。在创建Cookie时,指定一个名称和值。每个Cookie都必须有一个惟一的名称,以便浏览器读取时可以识别它。因为Cookie是按名称存储的,因此多个Cookie名称相同时,新的Cookie值会覆盖掉之前的。

可以设置Cookie的日期和过期时间。当用户访问写Cookie的站点时,浏览器会删除过期的Cookie。Cookie的有效期可以是50年。

如果没有设置Cookie的过期时间,就创建了Cookie,那么它并不会存储在用户的硬盘上。这种Cookie是作为用户会话信息的一部分来维护的。当用户关闭浏览器时,cookie就会被丢弃。像这样的非持久cookie对于需要在短时间内存储的信息非常有用,或者出于安全原因,不应该将其写入到客户机计算机上的磁盘上。例如,如果用户正在使用公共计算机,而不希望将cookie写入磁盘,则非持久性cookie非常有用。

您可以通过多种方式将Cookie添加到Cookie集合中。下面的例子展示了两个编写Cookie的方法:

//第一种
Response.Cookies["userName"].Value = "patrick";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);
//第二种
HttpCookie aCookie = new HttpCookie("lastVisit");
aCookie.Value = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

该示例将两个Cookie添加到Cookie集合中,其中一个名为用户名,另一个为上次访问时间。对于第一种方法,Cookie集合的值可以直接读写。因为Cookie继承自NameObjectCollectionBase集合类型,所以可以直接获取Cookie。

对于第二种方法,创建一个HttpCookie对象的实例,设置它的属性,然后通过Add方法将其添加到cookie集合中。Cookie的名称通过构造函数添加。

这两个示例都完成了相同的任务,将Cookie写入浏览器。在这两种方法中,过期值必须为DateTime类型。因为所有的Cookie值都以字符串形式存储,所以日期时间值会转换为字符串。

多个值的Cookie

Cookie可以存储一个值,比如用户名或最后一次访问。也可以在一个Cookie中存储多个键值对。键值对被称为子键。(子键的布局非常类似于URL中的查询字符串。)例如,您可以创建一个名为userInfo的cookie,它具有子健userName和lastVisit,而不是创建两个单独的Cookie。

子健可以将相关的或类似的信息放入一个Cookie中。如果所有信息都在一个Cookie中,Cookie属性如过期将应用于所有信息。(相反,如果您想为不同类型的信息分配不同的过期日期,则应该将信息存储在单独的cookie中。)

带有子键的Cookie也可以帮助限制Cookie文件的大小。之前提到,Cookie通常被限制为4096字节,并且每个站点能存储20多个Cookie。通过使用一个带有子键的Cookie,可以降低站点Cookie数量的限制。此外,一个Cookie自身就占用了大约50个字符(过期信息,等等),加上您存储在其中的值的长度,所有这些值都指向4096字节的限制。如果您存储5个子键而不是5个单独的cookie,您可以节省单个Cookie的开销,并且还可以节省大约200个字节。

创建有子键的Cookie:

//第一种
Response.Cookies["userInfo"]["userName"] = "patrick";
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
//第二种
HttpCookie aCookie = new HttpCookie("userInfo");
aCookie.Values["userName"] = "patrick";
aCookie.Values["lastVisit"] = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

Cookie作用域

默认情况下,一个站点的有过期时间的所有Cookie都存储在客户硬盘上,请求该网站时所有的Cookie都被发送到服务器。换句话说,网站上的每一个页面都能获得该站点的所有Cookie。但是,您可以通过两种方式来限制Cookie的范围:

  • 将Cookie的范围限制在服务器上的一个文件夹中,这允许您将Cookie限制在站点上的一个应用程序中。
  • 将范围设置为域,允许您指定域中的哪些子域可以访问cookie。

要将cookie限制在服务器上的一个文件夹中,可以设置cookie的路径属性,如下面的例子:

HttpCookie appCookie = new HttpCookie("AppCookie");
appCookie.Value = "written " + DateTime.Now.ToString();
appCookie.Expires = DateTime.Now.AddDays(1);
appCookie.Path = "/Application1";
Response.Cookies.Add(appCookie);

路径既可以是站点根下的物理路径,也可以是虚拟路径。这样做的效果是,Cookie只可用于Application1文件夹或虚拟根目录中的页面。例如,如果你的网站是www.contoso.com,在前面的示例中创建的Cookie可以与路径http://www.contoso.com/Application1/页面,该文件夹下任何页面。然而,Cookie不会在其他应用程序中可用的页面,比如http://www.contoso.com/Application2/或者http://www.contoso.com/

Cookie的限制和作用域

默认情况下,Cookie与特定的域相关联。
例如,如果您的站点是www.contoso.com,那么当用户请求该站点的任何页面时,您所写的Cookie将被发送到服务器。
(这可能不包括带有特定路径值的cookie。)
如果你的站点有子域名,例如,contoso.com,sales.contoso.com,以及support.contoso.com,那么你就可以把Cookies与特定的子域名联系起来。

代码示例:

Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "support.contoso.com";

当域以这种方式设置时,Cookie将只在指定子域中的页面可用。您还可以使用域属性来创建一个可以在多个子域中共享的Cookie,如下面的示例所示:

Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "contoso.com";

此时Cookie既可以主域,也可以用于sales.contoso.com和support.contoso.com等子域。


读取Cookie

当浏览器向服务器发出请求时,Cookie会随着请求一起发送到服务器上。在你的应用程序,您可以使用HttpRequest来读取cookie。

代码示例:

if(Request.Cookies["userName"] != null)
{
    HttpCookie aCookie = Request.Cookies["userName"];
    var cookiText = Server.HtmlEncode(aCookie.Value);
}

在尝试获取Cookie的值之前,应该确保Cookie存在;如果Cookie不存在,将得到NullReferenceException异常。还要注意,HtmlEncode方法被调用来对Cookie的内容进行编码。这确保了恶意用户没有将可执行脚本添加到Cookie中。

在Cookie中读取子键的值也类似于设置它。下面的代码示例展示了获取子键值的一种方法

if(Request.Cookies["userInfo"] != null)
{
    var name = 
        Server.HtmlEncode(Request.Cookies["userInfo"]["userName"]);

    var visit =
        Server.HtmlEncode(Request.Cookies["userInfo"]["lastVisit"]);
}

读取键值对lastVisit的值,该值之前被设置为DateTime类型。但是Cookie将值存储为字符串,因此如果您想使用lastVisit的值作为日期,则必须将其转换为适当的类型。

DateTime dt= DateTime.Parse(Request.Cookies["userInfo"]["lastVisit"]);

Cookie中的子键是NameValueCollection类型。因此,获取子键的另一种方法是获取子键集合,然后按名称提取子键值,如下面的示例所示:

if(Request.Cookies["userInfo"] != null)
{
    System.Collections.Specialized.NameValueCollection  UserInfoCookieCollection;
    UserInfoCookieCollection = Request.Cookies["userInfo"].Values;
   var name = 
        Server.HtmlEncode(UserInfoCookieCollection["userName"]);
    var visit =
        Server.HtmlEncode(UserInfoCookieCollection["lastVisit"]);
}

Cookie的过期时间

浏览器负责管理Cookie,Cookie的过期时间和日期帮助浏览器管理其存储的Cookie。因此,虽然您可以读取Cookie的名称和值,但是您不能读取cookie的过期日期和时间。当浏览器向服务器发送Cookie信息时,浏览器不包含过期信息。(Cookie的过期属性总是返回一个日期时间值为0。)如果您担心cookie的过期日期,您必须重新设置它。

读取Cookie集合

获取所有的Cookie

代码示例;

System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
for(int i=0; i<Request.Cookies.Count; i++)
{
    aCookie = Request.Cookies[i];
    output.Append("Cookie name = " + Server.HtmlEncode(aCookie.Name) 
        + "<br />");
    output.Append("Cookie value = " + Server.HtmlEncode(aCookie.Value)
        + "<br /><br />");
}

上一个示例的有一个不足的地方,如果cookie有子键,会将子键作为单个name/value字符串显示。您可以读取cookie的haskey属性,以确定cookie是否有子键。如果有,您可以读取子键集合以获得单独的子键名和值。
您也可以通过索引值直接从值集合中读取子键值。相应的子键名可以在值集合的AllKeys成员中找到,它返回一个字符串数组。您还可以使用值集合的键值。但是,AllKeys属性在第一次被访问时被缓存。相反,键属性在每次访问时都构建一个数组。由于这个原因,在相同页面请求的上下文中,AllKeys属性要快得多。

下面的例子显示了前面的示例的修改。它使用HasKeys属性来测试子键,如果检测到子键,那么这个示例将从值集合中获得子键:

for(int i=0; i<Request.Cookies.Count; i++)
{
    aCookie = Request.Cookies[i];
    output.Append("Name = " + aCookie.Name + "<br />");
    if(aCookie.HasKeys)
    {
        for(int j=0; j<aCookie.Values.Count; j++)
        {
            subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys[j]);
            subkeyValue = Server.HtmlEncode(aCookie.Values[j]);
            output.Append("Subkey name = " + subkeyName + "<br />");
            output.Append("Subkey value = " + subkeyValue + 
                "<br /><br />");
        }
    }
    else
    {
        output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
            "<br /><br />");
    }
}

或者,您可以将子键提取为NameValueCollection对象,如下面的例子所示:

System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
string subkeyName;
string subkeyValue;

for (int i = 0; i < Request.Cookies.Count; i++)
{
    aCookie = Request.Cookies[i];
    output.Append("Name = " + aCookie.Name + "<br />");
    if (aCookie.HasKeys)
    {
        System.Collections.Specialized.NameValueCollection CookieValues = 
            aCookie.Values;
        string[] CookieValueNames = CookieValues.AllKeys;
        for (int j = 0; j < CookieValues.Count; j++)
        {
            subkeyName = Server.HtmlEncode(CookieValueNames[j]);
            subkeyValue = Server.HtmlEncode(CookieValues[j]);
            output.Append("Subkey name = " + subkeyName + "<br />");
            output.Append("Subkey value = " + subkeyValue + 
                "<br /><br />");
        }
    }
    else
    {
        output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
            "<br /><br />");
    }
}

Cookie的删除和修改

修改Cookie

不能直接在获取到Cookie后就修改Cookie的值,因为Cookie存储在用户的硬盘上(Request.Cookies[“Key”].Value=”some”,在这里是不起作用的),必须在Response.Cookies[“Key”].Value=”SomeNew”中修改才可以。其实就是服务器中设置的Cookie新值,覆盖了用户浏览地上的Cookie的旧值。

代码示例:

int counter;
if (Request.Cookies["counter"] == null)
    counter = 0;
else
{
    counter = int.Parse(Request.Cookies["counter"].Value);
}
counter++;

Response.Cookies["counter"].Value = counter.ToString();
Response.Cookies["counter"].Expires = DateTime.Now.AddDays(1);

删除Cookie

将Cookie从用户的硬磁盘上删除,和修改Cookie原理是一样的。不能直接删除Cookie,因为Cookie在用户的硬盘上。但是,可以创建一个新Cookie,其名称与要删除的Cookie相同,但要将Cookie的过期时间设置为比今天更早的日期。当浏览器检查Cookie的过期时间,浏览器将丢弃已经过时的Cookie。

代码示例:

HttpCookie aCookie;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i<limit; i++)
{
    cookieName = Request.Cookies[i].Name;
    aCookie = new HttpCookie(cookieName);
    aCookie.Expires = DateTime.Now.AddDays(-1);
    Response.Cookies.Add(aCookie);
}

子键的修改和删除

修改一个单独的子键与创建它是一样的

如:

Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);

要删除一个单独的子键,您可以操作Cookie的值集合,该集合包含子键。
首先从Cookie集合中获取一个指定的Cookie,然后调用该cookie值集合的remove方法,参数即为要删除的子键名称,再把该Cookie添加到集合中。

如下代码示例:

string subkeyName;
subkeyName = "userName";
HttpCookie aCookie = Request.Cookies["userInfo"];
aCookie.Values.Remove(subkeyName);
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

Cookies安全性

Cookie的安全性问题类似于从客户端获取数据。对于应用程序来说,可以把Cookie看作是另一种形式的用户输入。因为Cookie是保存在用户自己的硬盘上,所以Cookie对用户来说是可见的,也是可以修改的。

因为Cookie对用户是可见的所以不能在Cookie中存储敏感数据,比如用户名、密码、信用卡号等等。

因为Cookie也是可修改的,所以对程序来说从Cookie获取的信息,也需要验证和判断。不能简单的认为Cookie中的数据就和我们预期的数据一样。

Cookie是在浏览器和服务器之间是作为纯文本发送的,任何能够拦截Web流量的人都可以拦截Cookie。但是可以设置Cookie只有在使用安全套接字层(SSL)的情况下才会传输Cookie,这样在传输时会对Cookie加密。但是在用户的硬盘上,Cookie就不受SSL保护了。


确定浏览器是否接受cookie

用户可以设置浏览器拒绝Cookie。如果不能写入Cookie,也不会抛出错误。同样,浏览器也不会向服务器发送关于当前Cookie设置的任何信息。

客户端验证

最简单的是使用JS来判断

  if (navigator.cookieEnabled) {
        alert("Cookie 可用");
    }
    else {
        alert("Cookie 禁用");
    }

服务端验证

cookie属性并不表示是否启用了cookie。它只表明当前浏览器本身是否支持cookie。

在服务端判断Cookie是否被接受的一种方法是尝试写一个Cookie,然后再试着读取该Cookie。如果不能读取所编写的Cookie,那么就可以假定浏览器关闭了Cookie。


如有不对,请多多指教


参考: