# 查看dll/lib/exe是32位还是64位

  • 找到dumpbin.exe,x86和x64文件夹下的都可以,在当前目录 cmd
C:\Program Files\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29\bin\Hostx86\x86
  • 找到自己要测试的dll/lib/exe文件位置,复制好地址
  • 在命令行输入命令 格式为bumpbin.exe /headers 文件位置\test.lib

# WebMethod

前台jquery代码:

$(function () {
  $("#btnfix").click(function () {
		 $.ajax({
				 type: "post",
				 url: "fix.aspx/test",
				 contentType: "application/json; charset=utf-8",
				 dataType: "json",
				 success: function (data) {
					 console.log(data.d);
				 },
				 error: function (err) {
					 alert(err);
				 }
		  });
	 });
});

后台代码:

//引用Web.Services命名空间
using System.Web.Services; 

public partial class Fix : System.Web.UI.Page
{ 
    protected void Page_Load(object sender, EventArgs e)
    {
		
	}
	
    //添加Attribute
    [WebMethod]   
	//方法设为静态
    public static string test()   
    {
        return "hello world";
    }
}

# HTTP请求

# HttpWebRequest

这是.NET最初开发用于使用HTTP请求的标准类,在当前业务中已经很少使用,由于其更加底层,需要处理一些细节

  • HttpWebRequest可以让开发者控制请求/响应流程的各个方面,如 timeouts, cookies, headers
  • HttpWebRequest不会阻塞UI线程。如当从响应慢的服务器下载大文件时,应用程序的UI不会停止响应
  • HttpWebRequest通常和WebResponse一起使用,一个发送请求,一个获取数据
  //POST方法
public static string HttpPost(string Url, string postDataStr)
{
  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
  request.Method = "POST";
  request.ContentType = "application/x-www-form-urlencoded";
  Encoding encoding = Encoding.UTF8;
  byte[] postData = encoding.GetBytes(postDataStr);
  request.ContentLength = postData.Length;
  Stream myRequestStream = request.GetRequestStream();
  myRequestStream.Write(postData, 0, postData.Length);
  myRequestStream.Close();
  HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  Stream myResponseStream = response.GetResponseStream();
  StreamReader myStreamReader = new StreamReader(myResponseStream, encoding);
  string retString = myStreamReader.ReadToEnd();
  myStreamReader.Close();
  myResponseStream.Close();

  return retString;
}

//GET方法
public static string HttpGet(string Url, string postDataStr)
{
  string postData = Url + (postDataStr == "" ? "" : "?") + postDataStr;
  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postData);
  request.Method = "GET";
  request.ContentType = "text/html;charset=UTF-8";
  HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  Stream responseStream = response.GetResponseStream();
  StreamReader streamReader =new StreamReader(responseStream,Encoding.GetEncoding("utf-8"));
  string retString = streamReader.ReadToEnd();
  streamReader.Close();
  responseStream.Close();
  return retString;
}

# WebClient

WebClient是一种更高级别的抽象,是HttpWebRequest为了简化最常见任务而创建的,使用过程中你会发现他缺少基本的header,timeoust的设置,不过这些可以通过继承httpwebrequest来实现

  • WebClient比WebRequest更加简单,它相当于封装了request和response方法
  • Webclient和WebRequest继承的是不同类,两者在继承上没有任何关系
  • 使用WebClient可能比WebRequest直接使用更慢(大约几毫秒)
public class WebClientHelper
  {
    public static string DownloadString(string url)
    {
      WebClient wc = new WebClient();
      //wc.BaseAddress = url;  //设置根目录
      wc.Encoding = Encoding.UTF8;  //设置按照何种编码访问,如果不加此行,获取到的字符串中文将是乱码
      string str = wc.DownloadString(url);
      return str;
    }
    public static string DownloadStreamString(string url)
    {
      WebClient wc = new WebClient();
      wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36");
      Stream objStream = wc.OpenRead(url);
	  //新建一个读取流,用指定的编码读取,此处是utf-8
      StreamReader _read = new StreamReader(objStream, Encoding.UTF8);  
      string str = _read.ReadToEnd();
      objStream.Close();
      _read.Close();
      return str;
    }

    public static void DownloadFile(string url, string filename)
    {
      WebClient wc = new WebClient();
      wc.DownloadFile(url, filename);   //下载文件
    }

    public static void DownloadData(string url, string filename)
    {
      WebClient wc = new WebClient();
      byte [] bytes = wc.DownloadData(url);  //下载到字节数组
      FileStream fs = new FileStream(filename, FileMode.Create);
      fs.Write(bytes, 0, bytes.Length); 
      fs.Flush();
      fs.Close();
    }

    public static void DownloadFileAsync(string url, string filename)
    {
      WebClient wc = new WebClient();
      wc.DownloadFileCompleted += DownCompletedEventHandler;
      wc.DownloadFileAsync(new Uri(url), filename);
      Console.WriteLine("下载中。。。");
    }
    private static void DownCompletedEventHandler(object sender, AsyncCompletedEventArgs e)
    {
      Console.WriteLine(sender.ToString());  //触发事件的对象
      Console.WriteLine(e.UserState);
      Console.WriteLine(e.Cancelled);
      Console.WriteLine("异步下载完成!");
    }

    public static void DownloadFileAsync2(string url, string filename)
    {
      WebClient wc = new WebClient();
      wc.DownloadFileCompleted += (sender, e) =>
      {
        Console.WriteLine("下载完成!");
        Console.WriteLine(sender.ToString());
        Console.WriteLine(e.UserState);
        Console.WriteLine(e.Cancelled);
      };
      wc.DownloadFileAsync(new Uri(url), filename);
      Console.WriteLine("下载中。。。");
    }
  }

# HttpClient

目前业务上使用的比较多的是HttpClient

  • 适合用于多次请求操作,一般设置好默认头部后,可以进行重复多次的请求
  • HttpClient提供了异步支持,可以轻松配合async await 实现异步请求
  • WebClient也可以处理异步请求
public class HttpClientHelper
{
	public string PostAsync(string url, string strJson)
	{
		try
		{
			HttpContent content=new StringContent(strJson,Encoding.UTF8,"application/json");
			//设置了要使用的 SSL/TLS 协议版本为 TLS 1.2
			ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
			using (HttpClient client = new HttpClient())
			{
				var mediaType = new MediaTypeWithQualityHeaderValue("application/json");
				client.DefaultRequestHeaders.Accept.Add(mediaType);
				//client.DefaultRequestHeaders.Add("Authorization", "Basic " + GetToken());
				HttpResponseMessage res = client.PostAsync(url, content).Result;
				if (res.StatusCode == System.Net.HttpStatusCode.OK)
				{
					string str = res.Content.ReadAsStringAsync().Result;
					return str;
				}
				else
					return null;
			}
		}
		catch (Exception ex)
		{
			return null;
		}
	}
    
	//post同步请求方法
	public async Task<string> PostUrlencodedAsync(string url, Dictionary<string, string> dic)
	{
		using (HttpClient _httpClient = new HttpClient())
	    {
	        HttpContent content = new FormUrlEncodedContent(dic);
			var mediaType = new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded");
	        content.Headers.ContentType = mediaType;
	        var response = await _httpClient.PostAsync(url, content);
	        return await response.Content.ReadAsStringAsync();
	    }
	}
	public aysnc Task<string> PostJson(string url, string strJson)
	{
		try
		{
			HttpContent content=new StringContent(strJson,Encoding.UTF8,"application/json");
			using (HttpClient client = new HttpClient())
			{
				var response = await client.PostAsync(url, content);
				return await response.Content.ReadAsStringAsync();
			}
		}
		catch (Exception ex)
		{
			return null;
		}
	}

	//get请求
	public string Get(string url)
	{
		try
		{
			using (HttpClient client = new HttpClient())
			{
				var responseString = client.GetStringAsync(url);
				return responseString.Result;
			}
		}
		catch (Exception ex)
		{
			return null;
		}
	}
}

# FluentHttpClient

FluentHttpClient 是用于 REST API 的现代异步 HTTP 客户端, 多平台支持 Linux、Mac 和 Windows。多框架支持,.NET, .NET Core, .NET Framework, .NET Standard 等。

//从 Nuget 中安装 Pathoschild.Http.FluentClient
Blog result = await new FluentClient("https://example.org/api")
   .GetAsync("blogs")
   .WithArgument("id", 15)
   //支持使用WithAuthentication WithBasicAuthentication WithBearerAuthentication 添加认证信息
   .WithBearerAuthentication(token)
   .As<Blog>();

这是一个简单的 Get 请求,并把响应内容反序列化为 Item 类

Item item = await new FluentClient()
   .GetAsync("https://example.org/api/items/14")
   .As<Item>();

还可以定义公共的客户端(这可以使用内置连接池提高性能),然后在构造函数中设置 URL

using var client = new FluentClient("https://example.org/api");

//客户端库提供了开箱即用的DELETE、GET、POST、PUT和方法
Item item = await client
   .GetAsync("items/14")
   .As<Item>();

可以使用匿名对象向请求 URL 添加任意数量的参数

await client
   .PostAsync("items/14")
   .WithArguments(new { page = 1, search = "some search text" });

//或者用字典
await client
   .PostAsync("items/14")
   .WithArguments(new Dictionary<string, object> {});

//或者单独设置每个参数
await client
   .PostAsync("items/14")
   .WithArgument("page", 1)
   .WithArgument("search", "some search text");

可以直接在 POST 或 PUT 中添加请求体

await client.PostAsync("search", new SearchOptions());

//或者使用下面的方式
await client
   .GetAsync("search")
   .WithBody(new SearchOptions());

设置请求头

await client
   .PostAsync("items/14")
   .WithHeader("User-Agent", "Some Bot/1.0.0")
   .WithHeader("Content-Type", "application/json");

默认情况下,客户端库不会重试失败的请求,如果需要重试的话,也容易配置

client
   .SetRequestCoordinator(
      maxRetries: 3,
      shouldRetry: request => request.StatusCode != HttpStatusCode.OK,
      getDelay: (attempt, response) => TimeSpan.FromSeconds(attempt * 5)       
   );

# 集成单点登录

  • 通过Nuget安装DotNetCasClient包
  • Web.config文件中自动增加相关配置,共6处,主要调整2处
<authentication mode="Forms">
 <forms name=".DotNetCasClientAuth" 
		//CAS服务端登录地址
		loginUrl="http://111.34.76.98:8080/cas/login" 
		defaultUrl="~/Default/Index" 
		cookieless="UseCookies" 
		path="/" />
</authentication>
<authorization>
 //所有用户都需要单点登录
 <deny users="?" />
</authorization>
<authorization>
 //所有用户都不需要单点登录
 <allow users="*"/>
</authorization>
//需要设置单个页面时则在页面上添加特性:Authorize

<!--cas开始 配置casClientConfig:
   casserverloginurl URL CAS登录表单。
   casserverurlprefix CAS服务器应用程序根。
   ServerName 客户端应用程序的地址
   ticketvalidatorname 票验证器验证CAS票使用特定的协议名称。有效值是cas10 cas20 saml11
   singlesignout 单点登出。
   proxyTicketManager="CacheProxyTicketManager"  不要添加,否则会重定向
-->
<casClientConfig casServerLoginUrl="http://111.34.76.98:8080/cas/login" 
				 casServerUrlPrefix="http://111.34.76.98:8080/cas/" 
				 serverName="http://10.3.1.25:8080" 
				 notAuthorizedUrl="~/Admin/Login" 
				 cookiesRequiredUrl="~/CookiesRequired.aspx" 
				 redirectAfterValidation="true" 
				 gateway="false" 
				 renew="false" 
				 singleSignOut="true" 
				 ticketTimeTolerance="5000" 
				 ticketValidatorName="Cas20"  
				 serviceTicketManager="CacheServiceTicketManager" 
				 gatewayStatusCookieName="CasGatewayStatus" 
/>
  • 获取用户信息
string userName = User.Identity.Name;//工号
LogHelper.Info(userName.ToJson());

HttpCookie ticketCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(ticketCookie.Value);
CasAuthenticationTicket casTicket = CasAuthentication.ServiceTicketManager
                                                     .GetTicket(ticket.UserData);


//获得所有传递过来的用户属性
Dictionary<string, string> userAttrs = new Dictionary<string, string>();
foreach (KeyValuePair<string, IList<string>> attribute in casTicket.Assertion.Attributes)
{
	string key = attribute.Key;
	LogHelper.Info("key:" + key + "::::" + attribute.Value);
	StringBuilder builder = new StringBuilder();
	foreach (string valuePart in attribute.Value)
	{
		builder.AppendLine("        " + valuePart);
	}
	userAttrs.Add(key, builder.ToString());

}
  • 退出登录
 [Authorize]
 public ActionResult LoginOff()
 {
    FormsAuthentication.SignOut();
    string url="http://sso.demo.com:8070/cas/logout?service=http://sso.demo.com:8070/cas/login"
    return Redirect(url);
 }