.NET开发经验小结
1.Http通信
这是一个好东西,如果想做通信协议方面的事,用HttpHandler将非常容易实现。 但是安全性,还得靠协议的设计了。
通信,当然是有服务端和客户端。服务端接收请求(Request)并进行处理返回内容(Response)就可以了。
小示例: 在VS的WEB网站项目或者WEB服务项目中新建一个“一般处理程序”ashx,然后只要在ProcessRequest中写入对请求的处理就可以了。
服务端:
public class HelloHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//从客户端接收到请求并,将POST的内容转换为字符串
StreamReader sr = new StreamReader(context.Request.InputStream);
string postData = sr.ReadToEnd();
sr.Close();
//然后对字符串 也就是根据协议进行处理并返回内容
string resultData = xxxNamespace.doSomething(postData);
//向客户端返回结果
context.Response.ClearContent();
context.Response.ContentType = "text/plain";
context.Response.Write(resultData);
context.Response.Flush();
context.Response.End();
}
}
客户端的通信类:
public class HttpCommunicate
{
/// <summary>
/// 通过POST方式向某地址发出请求,然后返回HttpWebRepsonse
/// </summary>
/// <param name="url"></param>
/// <param name="postData"></param>
/// <returns></returns>
public static HttpWebResponse MethodPost(string url, string postData)
{
byte[] bs = Encoding.ASCII.GetBytes(postData);
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.Timeout = 30000;
req.Method = "POST";
req.ContentLength = bs.Length;
Stream reqStream = null;
try
{
reqStream = req.GetRequestStream();
//写入流
reqStream.Write(bs, 0, bs.Length);
reqStream.Flush();
reqStream.Close();
}
catch
{
if (reqStream != null)
{
reqStream.Close();
}
throw new Exception("服务器无效应");
}
return (HttpWebResponse)req.GetResponse();
}
/// <summary>
/// 通过POST方式获取URL的内容
/// </summary>
/// <param name="url"></param>
/// <param name="postData"></param>
/// <returns></returns>
public static string GetContentByMethodPost(string url, string postData)
{
return GetContentFromHttpWebResponse(MethodPost(url, postData));
}
/// <summary>
/// 将数据流转换成字符串
/// </summary>
/// <param name="httpwebresponse"></param>
/// <returns></returns>
public static string GetContentFromHttpWebResponse(HttpWebResponse httpwebresponse)
{
string result = null;
StreamReader reader = null;
try
{
reader = new StreamReader(httpwebresponse.GetResponseStream());
result = reader.ReadToEnd();
reader.Close();
}
catch(Exception ex)
{
reader.Close();
throw new Exception(ex.Message);
}
return result;
}
/// <summary>
/// 通过GET方式向某地址发出请求,然后返回HttpWebRepsonse
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static HttpWebResponse MethodGet(string url)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.Timeout = 10000;
req.Method = "GET";
HttpWebResponse wr = null;
try
{
wr = (HttpWebResponse)req.GetResponse();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return wr;
}
/// <summary>
/// 通过GET方式获取URL地址的内容
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static string GetContentByMethodGet(string url)
{
return GetContentFromHttpWebResponse(MethodGet(url));
}
}
只要学会以上2个东东应用就能够进行通信了。
2. 动态加载TABLE 动态对TABLE进行打印
ASP.NET中动态的加载相同的控件,并且激发相同的事件是难以实现的。
需求:某个页面所要加载的数据表是动态生成的,而这些数据表还要有个打印按钮,只打印指定表的数据。
解决:通过JavaScript和Div的方法来实现这个需求。JavaScript可以通过指定Html中DIV的ID来获得DIV元素里的内容取出来。然后将该内容中的Html打印到另一个窗口中。再通过浏览器的打印功能实现。
其代码如下:
function printPage(divid) {
var printarea =document.getElementById(divid);
if(printarea==null || printarea.getAttribute('visible')==false)
return;
var newWin = window.open('Order_Printer.htm','','');
var titleHTML = printarea.innerHTML;
var re=new RegExp('"TEXT-ALIGN: center"',"g");
//把打印按钮隐藏
titleHTML = titleHTML.replace(re,'"display:none;"');
newWin.document.write(titleHTML);
newWin.document.location.reload();
}
为了达到动态生成数据表的目标,需要一个用户控件。这个用户控件要为DIV段自动生成ID 并且 其所带的按钮也要指定上文中JavaScript的方法函数的打印这个ID。其代码如下:
用户控件ascx:
<asp:Panel ID="panelself" runat="server">
<asp:Literal ID="lblHeader" runat="server"></asp:Literal>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
<asp:Literal ID="lblBottom" runat="server"></asp:Literal>
<div id='printbtn' style='text-align:center;'>
<asp:Literal ID="lblPrintBtn" runat="server"></asp:Literal>
</div>
</asp:Panel>
用户控件ascx.cs:
public partial class UserControl_PrintTemplete: System.Web.UI.UserControl
{
/// <summary>
/// 这个编号需要唯一值否则打印按钮无法找到所要打印的内容
/// </summary>
/// <param name="printGUID"></param>
public void MadePrinter(string printDIVID)
{
lblHeader.Text = @"<div id='pt" + printDIVID + "'>";
lblBottom.Text = @"</div>";
lblPrintBtn.Text = @" <input id='btn" + printDIVID + "' type='button' value='打 印' onclick=\"printPage('pt" + printDIVID + "');\"/>";
}
}
最后一步是ASP.NET页面的实现,为页面添加打印模板用户控件。
其相关代码如下:
//加载打印模板
UserControl_PrintTemplete PrintTemp = (UserControl_PrintTemplete)Page.LoadControl("UserControl_PrintTemplete.ascx");
//将数据进填充到用户控件中的GridView中
PrintTemp.doSomeThing(datas);
//构建打印按钮和DIV,必须有个唯一ID
PrintTemp.MadePrinter((printerid++).ToString());
//添加到当前页面中
this.panelx.Controls.Add(PrintTemp);
这样一来最终打开页面,所生成的Html代码。某个Table下都有一个Button按钮,而这个按钮所驱动的OnClick事件中的函数 printPage(divid),其参数divid就是B包含此Table的DIV,此DIV的ID为上文代码中的“printerid”。
3. 在网页上导出EXCEL
需求:在上面的段落中我们能够成功的拼凑出多个Table并且打印,然后我们还要将那些Table都导出EXCEL。
其相关代码如下:
//导出所有表格EXCEL
protected void btnExport_Click(object sender, EventArgs e)
{
//先将DATATABLE动态生成
BindGrid();
System.IO.StringWriter tw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter(tw);
foreach (Control cr in panelx.Controls) //遍历打印模板的用户控件
{
cr.RenderControl(hw);//将HTML扔进HtmlTextWriter中
}
//告诉客户端其内容的类型,并将数据写出。
string attachment = "attachment; filename="+DateTime.Now.ToShortDateString()+".xls";
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
Response.Charset = "UTF-8";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8");
Response.Write(tw.ToString());
Response.End();
}
4. 硬盘容量显示
需求:要求在WEB上显示 服务器的硬盘信息
解决:在命名空间System.Management中有SelectQuery好东东,可以用来查询很多系统信息。
/// <summary>
/// 返回的数据表 列名:DeviceID=驱动盘符名,Size=总容量,FreeSpace=空闲空间
/// </summary>
/// <returns></returns>
public DataTable GetDiskInfo()
{
DataTable dt = new DataTable();
dt.Columns.Add("DeviceID");
dt.Columns.Add("Size");
dt.Columns.Add("FreeSpace");
SelectQuery selectQuery = new
SelectQuery("Win32_LogicalDisk");
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(selectQuery);
foreach (ManagementObject disk in searcher.Get())
{
string[] str = new string[3];
str[0] = disk["DeviceID"].ToString(); //盘符ID
//极有可能出现访问权限的限制 所以要用TRY CATCH
try
{
UInt64 disksize = 0;
if (UInt64.TryParse(disk["Size"].ToString(), out disksize)) //总容量
{
str[1] = (disksize / 1024 / 1024 /1024).ToString("0.0") + " GB";
}
}
catch
{
str[1] = "未知";
}
try
{
UInt64 diskfreespace = 0;
if (UInt64.TryParse(disk["FreeSpace"].ToString(), out diskfreespace)) //空闲容量
{
str[2] = (diskfreespace / 1024 / 1024 / 1024).ToString("0.0") + " GB";
}
}
catch
{
str[2] = "未知";
}
dt.Rows.Add(str);
}
return dt;
}
5. 进程状态与CPU利用率显示
需求:要求在WEB上显示 服务器进程信息 和 CPU利用率
解决:这是一个比较麻烦的事,因为ASP.NET不像C++可以直接拿系统函数去查进程信息。。。必须绕不少圈子。不过还是有办法查出来。需要两个命名空间System.Diagnostics;System.Management;
/// <summary>
/// CPU使用率
/// </summary>
private double _cpudata = 0.0;
/// <summary>
/// 进程信息数据表
/// </summary>
private DataTable _processdatatable = null;
/// <summary>
/// 性能计数器,用于获取CPU空闲百分比
/// </summary>
private static PerformanceCounter mIdle = null;
/// <summary>
/// 性能计数器,用于获取CPU总利用率
/// </summary>
private static PerformanceCounter mTotal = null;
/// <summary>
/// 产生当前状态的进程与CPU使用率信息。 每次调用会更新。
/// </summary>
/// <returns></returns>
public void GenerateAllInfo()
{
if (mIdle == null)
mIdle = new PerformanceCounter("Process", "% Processor Time", "Idle");
if (mTotal == null)
mTotal = new PerformanceCounter("Process", "% Processor Time", "_Total");
double idlePercent = mIdle.NextValue(); // 空闲比率
double totalPercent = mTotal.NextValue(); //总使用比率
//初始化数据表
if (_processdatatable == null)
{
_processdatatable = new DataTable();
_processdatatable.Columns.Add("Name");
_processdatatable.Columns.Add("User");
_processdatatable.Columns.Add("CPU");
_processdatatable.Columns.Add("WorkingSet");
}
_processdatatable.Rows.Clear(); //清除无用数据
double cputotal = 0;//
Process[] pos = Process.GetProcesses();
//遍历每个进程的信息产生基础数据
for(int i= 0; i<pos.Length ; i++)
{
//某些进程无法访问可能无法访问 所以放个TRY CATCH
try
{
string[] str = new string[4];
str[0] = pos[i].ProcessName;
str[1] = this.GetProcessUser(pos[i].Id);
str[2] = pos[i].TotalProcessorTime.TotalMilliseconds.ToString();
cputotal += pos[i].TotalProcessorTime.TotalMilliseconds; //计算总花费时间
str[3] = (pos[i].WorkingSet64 / 1024).ToString() + " K";
_processdatatable.Rows.Add(str);
}
catch
{
}
}
//算当前进程的CPU的花费时间 //第二次去拿总花费时间 - 之前拿的总花费时间 = 当前周期的花费时间
for (int i = 0; i < pos.Length ; i++ )
{
try
{
double cpuproc = 0; //该进程相关的时间花费
if (double.TryParse(_processdatatable.Rows[i]["CPU"].ToString(), out cpuproc))
{
_processdatatable.Rows[i]["CPU"] = (pos[i].TotalProcessorTime.TotalMilliseconds - cpuproc).ToString();
}
cputotal -= pos[i].TotalProcessorTime.TotalMilliseconds; //计算单周期花费时间
}
catch
{
}
}
cputotal = -cputotal;
//计算每个进程的CPU利用率
for (int i = 0; i < _processdatatable.Rows.Count; i++)
{
double tmp=0;
if(double.TryParse(_processdatatable.Rows[i]["CPU"].ToString(),out tmp)&&tmp!=0)
{
_processdatatable.Rows[i]["CPU"] = (Math.Abs(tmp / cputotal * 100)).ToString("0.0");
}
}
System.Threading.Thread.Sleep(500);
idlePercent = mIdle.NextValue();
totalPercent = mTotal.NextValue();
if (totalPercent == 0) //避免异常
{
_cpudata = 0;
}
else
{
// CPU利用率 = (总使用率-空闲率) / 总使用率
_cpudata =100 * (totalPercent-idlePercent)/totalPercent;
}
}