2009年6月28日
#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
namespace WebAppRequestUrl
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
WriteLine<string>("Request.Url.AbsolutePath", Request.Url.AbsolutePath);
WriteLine<string>("Request.Url.AbsolutePath.Split('/')[1]", Request.Url.AbsolutePath.Split('/')[1]);
WriteLine<string>("Request.Url.AbsoluteUri", Request.Url.AbsoluteUri);
WriteLine<string>("Request.Url.Authority", Request.Url.Authority);
WriteLine<string>("Request.Url.DnsSafeHost", Request.Url.DnsSafeHost);
WriteLine<string>("Request.Url.Fragment", Request.Url.Fragment);
WriteLine<string>("Request.Url.Host", Request.Url.Host);
WriteLine<UriHostNameType>("Request.Url.HostNameType",
Request.Url.HostNameType,
o => o.ToString());
WriteLine<bool>("Request.Url.IsAbsoluteUri", Request.Url.IsAbsoluteUri);
WriteLine<bool>("Request.Url.IsDefaultPort", Request.Url.IsDefaultPort);
WriteLine<bool>("Request.Url.IsFile", Request.Url.IsFile);
WriteLine<bool>("Request.Url.IsLoopback", Request.Url.IsLoopback);
WriteLine<bool>("Request.Url.IsUnc", Request.Url.IsUnc);
WriteLine<string>("Request.Url.LocalPath", Request.Url.LocalPath);
WriteLine<string>("Request.Url.OriginalString", Request.Url.OriginalString);
WriteLine<string>("Request.Url.PathAndQuery", Request.Url.PathAndQuery);
WriteLine<int>("Request.Url.Port", Request.Url.Port);
WriteLine<string>("Request.Url.Query", Request.Url.Query);
WriteLine<string>("Request.Url.Scheme", Request.Url.Scheme);
WriteLine<string[]>("Request.Url.Segments", Request.Url.Segments, o =>
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < o.Length; ++i)
{
sb.AppendFormat("<span style=\"color:blue;\">{0}</span> :{1}<br />", i, o[i]);
}
return sb.ToString();
});
WriteLine<bool>("Request.Url.UserEscaped", Request.Url.UserEscaped, o => (o == true ? "true" : "false"));
WriteLine<string>("Request.Url.UserInfo", Request.Url.UserInfo);
}
private void WriteLine<T>(string name, T output)
{
WriteLine<T>(name, output, o => o.ToString());
}
private void WriteLine<T>(string name, T output, Func<T, string> toString)
{
if (currentRow++ % 2 == 0)
{
Output("<div style=\"border:1px solid; background-color:#cccccc; padding:10px; font-family:Arial;\">");
}
else
{
Output("<div style=\"border:1px solid; background-color:#eeeeee; padding:10px; font-family:Arial;\">");
}
Output("<b style=\"color:blue;\">" + name + "</b> " + output.GetType().FullName + "<br /> ");
Output("<span style=\"font-family:consolas;\">" + toString(output) + "</span>");
Output("</div><br />");
}
private void Output(string s)
{
this.form1.InnerHtml += s;
this.form1.InnerHtml += "\n";
}
private int currentRow;
}
}
下面是输出:
Request.Url.AbsolutePath System.String
/Default.aspx
Request.Url.AbsolutePath.Split('/')[1] System.String
Default.aspx
Request.Url.AbsoluteUri System.String
http://localhost:17698/Default.aspx?myQuery=volnet
Request.Url.Authority System.String
localhost:17698
Request.Url.DnsSafeHost System.String
localhost
Request.Url.Fragment System.String
Request.Url.Host System.String
localhost
Request.Url.HostNameType System.UriHostNameType
Dns
Request.Url.IsAbsoluteUri System.Boolean
True
Request.Url.IsDefaultPort System.Boolean
False
Request.Url.IsFile System.Boolean
False
Request.Url.IsLoopback System.Boolean
True
Request.Url.IsUnc System.Boolean
False
Request.Url.LocalPath System.String
/Default.aspx
Request.Url.OriginalString System.String
http://localhost:17698/Default.aspx?myQuery=volnet
Request.Url.PathAndQuery System.String
/Default.aspx?myQuery=volnet
Request.Url.Port System.Int32
17698
Request.Url.Query System.String
?myQuery=volnet
Request.Url.Scheme System.String
http
Request.Url.Segments System.String[]
0 :/
1 :Default.aspx
Request.Url.UserEscaped System.Boolean
false
Request.Url.UserInfo System.String
/// <devdoc>
/// <para>
/// Terminates execution of the current page and begins execution of a new
/// request using the supplied URL path.
/// If preserveForm is false, the QueryString and Form collections are cleared.
/// </para>
/// </devdoc>
public void Transfer(string path, bool preserveForm) {
Page page = _context.Handler as Page;
if ((page != null) && page.IsCallback) {
throw new ApplicationException(SR.GetString(SR.Transfer_not_allowed_in_callback));
}
// execute child request
Execute(path, null, preserveForm);
// suppress the remainder of the current one
_context.Response.End();
}
都问页面跳转,然后大家都知道Server.Transfer与Request.Redirect的区别。
因为是页面跳转,所以理所应当地被用上了Response.End方法,而此举却引发了一些异常(http://support.microsoft.com/kb/312629)。
所以用Server.Execute就可以避免这个错误了。
详细如下:
对于 Response.End,调用 HttpContext.Current.ApplicationInstance.CompleteRequest 方法而不是 Response.End 以跳过 Application_EndRequest 事件的代码执行。
对于 Response.Redirect,请使用重载 Response.Redirect(String url, bool endResponse),该重载对 endResponse 参数传递 false 以取消对 Response.End 的内部调用。例如:
Response.Redirect ("nextpage.aspx", false);
如果使用此替代方法,将执行 Response.Redirect 后面的代码。
对于 Server.Transfer,请改用 Server.Execute 方法。
顺便让我们看看Response.End都做了些什么
/*
* Cancelles handler processing of the current request
* throws special [non-]exception uncatchable by the user code
* to tell application to stop module execution.
*/
/// <devdoc>
/// <para>Sends all currently buffered output to the client then closes the
/// socket connection.</para>
/// </devdoc>
public void End() {
if (_context.IsInCancellablePeriod) {
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
}
else {
// when cannot abort execution, flush and supress further output
if (!_flushing) { // ignore Reponse.End while flushing (in OnPreSendHeaders)
Flush();
_ended = true;
if (_context.ApplicationInstance != null) {
_context.ApplicationInstance.CompleteRequest();
}
}
}
}
关于InternalSecurityPermissions.ControlThread.Assert()请参考http://msdn.microsoft.com/zh-cn/library/system.security.codeaccesspermission.assert(VS.80).aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
namespace WebAppThreadAbortException
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Do1Nothing();
// Do1NothingWithoutException();
// Do2ResponseEnd();
// Do3Redirect();
// Do4Transfer();
}
private void Do1Nothing()
{
Thread.CurrentThread.Abort();
}
private void Do1NothingWithoutException()
{
try
{
Thread.CurrentThread.Abort();
}
catch
{
Thread.ResetAbort();
}
}
private void Do2ResponseEnd()
{
try
{
Response.End();
}
catch (ThreadAbortException ex)
{
Response.Write(FormatException(ex.ToString()));
}
}
private void Do3Redirect()
{
try
{
Response.Redirect("NextPage.aspx");
}
catch (ThreadAbortException ex)
{
Response.Write(FormatException(ex.ToString()));
}
}
private void Do4Transfer()
{
try
{
Server.Transfer("NextPage.aspx");
}
catch (ThreadAbortException ex)
{
Response.Write(FormatException(ex.ToString()));
}
}
private string FormatException(string exception)
{
return string.Format("<div style=\"border:1px solid; padding:10px; background-color:yellow;\">{0}</div>", exception);
}
}
}
疑问:
既然我们说Response.End将引发一个ThreadAbortException,但为何直接调用Response.End的时候并不会出现异常页面呢?但是我们在页面上直接使用Thread.CurrentThread.Abort(); 却会出现异常页面,请问这是为什么呢?
2009年6月27日
#
private static int HexToInt(char h) {
return( h >= '0' && h <= '9' ) ? h - '0' :
( h >= 'a' && h <= 'f' ) ? h - 'a' + 10 :
( h >= 'A' && h <= 'F' ) ? h - 'A' + 10 :
-1;
}
internal static char IntToHex(int n) {
Debug.Assert(n < 0x10);
if (n <= 9)
return(char)(n + (int)'0');
else
return(char)(n - 10 + (int)'a');
}
以上代码源自Microsoft ASP.NET HttpServerUtility.cs源码。
2009年6月14日
#
命题:如何获取本地局域网内的可用IP地址?
从这个命题,可以看出这里要解释的概念,什么是局域网?详见(http://baike.baidu.com/view/788.htm)
当然,在这篇文章中我们是指我们可以有效ping通的IP地址。
思路1:
穷举:
假设我们知道我们的IP地址为192.168.1.1 /24,即子网掩码为255.255.255.0,那么通过匹配192.168.1.*,所有可ping通的IP地址都为我们当前可获知的IP地址。
这里有一点需要解释一下,就是这个地址要ping地通,就以经验来告诉我们,这是错的。因为很多时候很多计算机显然连接在一个HUB或者SWITCH上,但是根本无法ping通,仅仅只是因为它的计算机可能的安全性问题所致。
但我们考虑到我们要ping通的计算机才有意义,因此,这种思路也是一种方案。
事实上,后续的几种方案依然存在这个问题。
穷举的方案详见:http://heisetoufa.javaeye.com/blog/253099
思路2:
利用DOS命令net view:http://tech.sina.com.cn/s/2006-04-07/1446895256.shtml
事实上这里要引进一种在.NET程序中利用DOS命令来解决的方案。
首先下面的类用来解决传递DOS命令的方案(很简单):
namespace WinFormShowLocalIPs
{
using System;
using System.Diagnostics;
public static class DOS
{
public static void CMD(
string commandNameOrFileName,
string arguments,
DataReceivedEventHandler callback)
{
try
{
Process process = new Process();
process.StartInfo.FileName = commandNameOrFileName;
process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += new DataReceivedEventHandler(callback);
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
process.Close();
}
catch (Exception ex)
{
throw new ArgumentException("启动DOS命令失败!", ex);
}
}
}
}
然后就是调用DOS命令,并解析运行DOS后返回值的步骤:
namespace WinFormShowLocalIPs
{
using System;
using System.Net;
using System.Diagnostics;
using System.Threading;
using System.Net.Sockets;
public class DnsHelper
{
public void AsynGetAddresses(DataReceivedEventHandler receivedHostEntry)
{
ReceivedHostEntry = receivedHostEntry;
DOS.CMD("net.exe", "view", process_OutputDataReceived);
}
private void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Data))
{
if (e.Data.StartsWith("\\\\"))
{
try
{
string hostName = e.Data.Substring(2).TrimEnd();
ResolveState ioContext = new ResolveState(hostName);
GetHostEntryFinished.Reset();
IAsyncResult result = Dns.BeginGetHostEntry(ioContext.HostName,
new AsyncCallback(GetHostAddressesCallback), ioContext);
if (GetHostEntryFinished.WaitOne())
{
if (ReceivedHostEntry != null)
{
ReceivedHostEntry(ioContext, e);
}
}
}
catch
{
}
}
}
}
ManualResetEvent GetHostEntryFinished = new ManualResetEvent(false);
void GetHostAddressesCallback(IAsyncResult ar)
{
ResolveState ioContext = (ResolveState)ar.AsyncState;
try
{
ioContext.IPs = Dns.EndGetHostEntry(ar);
}
catch(SocketException se)
{
ioContext.HasError = true;
ioContext.ErrorMessage = "GetHostEntry has error!";
ioContext.Error = se;
}
GetHostEntryFinished.Set();
}
public class ResolveState
{
string hostName;
IPHostEntry resolvedIPs;
public ResolveState(string host)
{
hostName = host;
}
public IPHostEntry IPs
{
get { return resolvedIPs; }
set { resolvedIPs = value; }
}
public string HostName
{
get { return hostName; }
set { hostName = value; }
}
private bool hasError = false;
public bool HasError
{
get
{
return hasError;
}
set
{
hasError = value;
}
}
public string ErrorMessage
{
get;
set;
}
public Exception Error
{
get;
set;
}
}
public DataReceivedEventHandler ReceivedHostEntry
{
get;
set;
}
}
}
然后就是界面调用的方案:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinFormShowLocalIPs
{
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.DirectoryServices;
using System.ComponentModel;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
lbIps.Width = 200;
}
private StringBuilder sb = new StringBuilder("Result:\n");
private void btnShowIps_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(
() =>
{
try
{
DnsHelper d = new DnsHelper();
d.AsynGetAddresses(ReceivedHostEntry);
SetLbIps(sb.ToString());
sb.Remove(0, sb.Length);
}
finally
{
InterfaceHelper.ShowWaitingEffect(false, null);
}
}));
thread.Start();
InterfaceHelper.ShowWaitingEffect(true, (o, args) => {
//AppendWaiting(args.Data);
string welcome = "Please wait!";
if (args.Count == 1)
{
SetLbIps(welcome);
AppendLbIps(string.Format("[{0}]", args.Count));
}
else
{
StringBuilder waiting = new StringBuilder();
SetLbIps(welcome);
AppendLbIps(string.Format("[{0}]", args.Count));
while (args.Count-- != 0)
{
waiting.Append(".");
}
AppendLbIps(waiting.ToString());
}
});
}
void ReceivedHostEntry(object sender, DataReceivedEventArgs e)
{
WinFormShowLocalIPs.DnsHelper.ResolveState state
= sender as WinFormShowLocalIPs.DnsHelper.ResolveState;
if (state != null && !state.HasError)
{
sb.AppendFormat("HostName:{0}\n", state.HostName);
foreach (IPAddress ip in state.IPs.AddressList)
{
sb.AppendLine(ip.ToString());
}
}
else if (state != null && state.HasError)
{
//sb.AppendLine("----------error start----------");
//sb.AppendLine(state.HostName);
//sb.AppendLine(state.ErrorMessage);
//sb.AppendLine("-----------error end-----------");
}
}
delegate void SetAsyncCallBack(string text);
void SetLbIps(string args)
{
if (lbIps.InvokeRequired)
{
SetAsyncCallBack d = new SetAsyncCallBack(SetLbIps);
this.Invoke(d, new object[] { args });
}
else
{
lbIps.Text = args;
}
}
void AppendLbIps(string args)
{
if (lbIps.InvokeRequired)
{
SetAsyncCallBack d = new SetAsyncCallBack(AppendLbIps);
this.Invoke(d, new object[] { args });
}
else
{
lbIps.Text += args;
}
}
}
}
上面的方案中包含以下有用信息:
1、对Windows 窗体控件进行线程安全调用(http://msdn.microsoft.com/zh-cn/library/ms171728.aspx)
2、如何显示进度条(文本进度条),基于多线程以及线程切换。
思路3:
利用DirectoryEntry来完成任务。关于DirectoryEntry,请参考MSDN(http://msdn.microsoft.com/zh-cn/library/system.directoryservices.directoryentry.aspx)
private void btnShowIPs2_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(
() =>
{
try
{
DirectoryEntry root = new DirectoryEntry("WinNT:");
foreach (DirectoryEntry Domain in root.Children)
{
//枚举工作组或域
sb.AppendLine(Domain.Name);
foreach (DirectoryEntry Computer in Domain.Children)
{
//枚举指定工作组或域的计算机
if (Computer.SchemaClassName.Equals("Computer"))
{
IPHostEntry ipHost;
try
{
ipHost = Dns.GetHostEntry(Computer.Name);
foreach (IPAddress ip in ipHost.AddressList)
{
sb.AppendFormat("{0}:", Computer.Name);
sb.AppendLine(ip.ToString());
}
}
catch
{
}
}
}
}
SetLbIps(sb.ToString());
sb.Remove(0, sb.Length);
}
finally
{
InterfaceHelper.ShowWaitingEffect(false, null);
}
}));
thread.Start();
InterfaceHelper.ShowWaitingEffect(true, (o, args) =>
{
AppendLbIps(args.Data);
});
}
关于InterfaceHelper类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace WinFormShowLocalIPs
{
public class InterfaceHelper
{
static Thread waitingThread = null;
static int waitingCount = 0;
public static void ShowWaitingEffect(bool showSwitch, EventHandler<InfoEventArgs> showHandler)
{
if (showSwitch && showHandler == null)
{
throw new ArgumentNullException("The handler can not be null!");
}
if (!showSwitch && waitingThread != null)
{
waitingThread.Abort();
waitingThread = null;
waitingCount = 0;
return;
}
showHandler(null, new InfoEventArgs("Please wait for a while.") { Count = waitingCount });
waitingThread = new Thread(new ThreadStart(
() =>
{
while (showSwitch)
{
++waitingCount;
showHandler(null, new InfoEventArgs(".") { Count = waitingCount });
Thread.Sleep(1000);
}
}));
waitingThread.Start();
}
public class InfoEventArgs : EventArgs
{
private string args = string.Empty;
public InfoEventArgs() { }
public InfoEventArgs(string args)
{
this.args = args;
}
public string Data
{
get { return args; }
set { args = value; }
}
public int Count
{ get; set; }
}
}
}
2009年5月28日
#
已经有很多文章来描述这个主题了,我这里就讲讲我的一些看法。
给你一份简历,你会怎么看?如果你不是每天吃饱了没事做专业面试的?你会怎么面?
如果给你一份简历,嗯,项目经历要介绍,但注意不是项目介绍,有人做了某某产品系统,让他做个介绍,他就开始跟我介绍这个产品,电话这头的我倒是顺便了解了一个新产品,但对他而言丝毫没有帮助,因为我很清晰,这个人肯定理解力或者表达力有欠缺,或者这个项目压根就没啥可提的。当然如果这个东西如果我感兴趣的话可能直接给你加分。
会的技术写,不会的技术不写,可能会可能不会的,宁可不写。很多职位不需要你从WPF,WCF,WF,Silverlight,MVC,Ajax,jQuery等全部都写进来,因为我通常只会挑选我见到的问,你不写你会WPF,我是不会问你的,特别是这个职位如果是ASP.NET的话,但是如果你有好几个项目都用了WPF,并且你声称自己小有牛劲的话,那你惨了,本来你不需要回答这个问题的,但现在你需要了,因为我可能也会一点,可能不如你,但你不一定比我见过的人牛,所以你可能被认为很差,或者认为学习态度有问题。如果你这个技术还是你其他技术中比较牛的,那说明你别的更一般,嗯,就挂了。
针对你应聘的岗位写经验,告诉我你在这方面很强大就好了,咱就考这方面,当然,如果你精通算法数据结构的话,或者在某些科学领域有所探索,请告诉我,因为大部分学计算机的人可能对这些基本能力很看重,起码我是这样,这样我会给你优先的机会。这也就包括你可能有些特长,比如特别喜欢请同事吃饭等,我都可以优先考虑。当然不要忽悠我!哈哈
如果要用英文写简历,请也带上中文,不要搞得自己很牛,因为有的人可能还愤青呢,就是看你假洋鬼子不录用你怎么招?因为今天有同事面对一箩筐的简历,决定让那个假洋鬼子去国外呆着,这里容不下他。中英文都有则显得专业,只有英文,当然我可以给你打个电话,但我同事不肯,这时候不知道吃亏的是谁?
如果你投递了简历,请保持手机在线!居然有人关机了!好吧,再见!本来是通过了,但因为通过的人比较多,需要再小筛一两个,现在你关机了,优先退出。
请务必在简历中写上手机号码!可能你的手机号码在邮件title中,或者在别的地方,但中间可能经历了QQ,MSN,U盘等中转,你的手机号码还在原来的地方,如果我只有一份简历,我会回去找回你的号码,如果我有一堆,那你就自动靠后了,直到我想起你来为止。所以请务必保持手机号码和简历的原子性。
不要写太长,简明扼要就可以,长,没人会觉得你了不起,美观点就可以了。有见到个简历,是用纵向平均分开的表格,这个没有关系,但是最右边一列类似详细内容,左边的全部都是10个字符以内的,造成了我拖动了4-5页纸,只看到一点点的信息。这很不好,当然我也不介意,因为你让我觉得简历太多了,我直接电话让你自我介绍好了。
去面试前务必检查带上几份简历,不要以为这个问题每个人都知道,不知道的居然远远超过知道的,太可恶了。
注意,记住,对你不会的尽量闭口不谈,不会的就说不会,不要忽悠我,点头也不代表同意你的观点,也可能在误导你,不过只是要套出你是真懂还是假懂。
祝大家都顺心如意,端午节快乐!更多信息请加入博客园“面试笔试”小组!
2009年3月19日
#
以下代码可以从http header中获取一个attribute的值。如:
String b = GetAttributeFromHeader(ContentType, "boundary");
private static String GetAttributeFromHeader(String headerValue, String attrName) {
if (headerValue == null)
return null;
int l = headerValue.Length;
int k = attrName.Length;
// find properly separated attribute name
int i = 1; // start searching from 1
while (i < l) {
i = CultureInfo.InvariantCulture.CompareInfo.IndexOf(headerValue, attrName, i, CompareOptions.IgnoreCase);
if (i < 0)
break;
if (i+k >= l)
break;
char chPrev = headerValue[i-1];
char chNext = headerValue[i+k];
if ((chPrev == ';' || chPrev == ',' || Char.IsWhiteSpace(chPrev)) && (chNext == '=' || Char.IsWhiteSpace(chNext)))
break;
i += k;
}
if (i < 0 || i >= l)
return null;
// skip to '=' and the following whitespaces
i += k;
while (i < l && Char.IsWhiteSpace(headerValue[i]))
i++;
if (i >= l || headerValue[i] != '=')
return null;
i++;
while (i < l && Char.IsWhiteSpace(headerValue[i]))
i++;
if (i >= l)
return null;
// parse the value
String attrValue = null;
int j;
if (i < l && headerValue[i] == '"') {
if (i == l-1)
return null;
j = headerValue.IndexOf('"', i+1);
if (j < 0 || j == i+1)
return null;
attrValue = headerValue.Substring(i+1, j-i-1).Trim();
}
else {
for (j = i; j < l; j++) {
if (headerValue[j] == ' ' || headerValue[j] == ',')
break;
}
if (j == i)
return null;
attrValue = headerValue.Substring(i, j-i).Trim();
}
return attrValue;
}
摘要:
内容涉及:form(表单)提交的相关细节。
2009年3月14日
#
The blog record any valuable point from the free book. 《Professional ASP.NET MVC1.0》!
The blog write by volnet.
1.Page 12/196
ASP.NET MVC projects by default have six top-level directories:
| Directory | Purpose |
| /Controllers | Where you put Controller classes that handle URL requests |
| /Models | Where you put classes that represent and manipulate data |
/Views
| Where you put UI template files that are responsible for rendering output |
| /Scripts | Where you put JavaScript library files and scripts (.js) |
| /Content | Where you put CSS and image files, and other non-dynamic/non-JavaScript content |
| /App_Data | Where you store data files you want to read/write. |
ASP.NET MVC does not require this structure. In fact, developers working on large applications will
typically partition the application up across multiple projects to make it more manageable (for example:
data model classes often go in a separate class library project from the web application). The default
project structure, however, does provide a nice default directory convention that we can use to keep
our application concerns clean.
2.Page 28/196
In a model-view-controller framework the term “model” refers to the objects that represent the data of
the application, as well as the corresponding domain logic that integrates validation and business rules
with it. The model is in many ways the “heart” of an MVC-based application, and as we’ll see later fundamentally drives the behavior of it.
3.Page 31/196
By default the LINQ to SQL designer automatically "pluralizes" table and column names when it creates
classes based on a database schema. For example: the "Dinners" table in our example above resulted in
a "Dinner" class. …
By default the LINQ to SQL designer also inspects the primary key/foreign key relationships of the tables,
and based on them automatically creates default "relationship associations" between the different
model classes it creates. For example, …
4.Page 42/196
We can use .NET’s regular expression support to implement this phone validation support. Below is a
simple PhoneValidator implementation that we can add to our project that enables us to add countryspecific
Regex pattern checks:
Click here to get code!
All these code is the same as before. (Click here to collapse!)
public class PhoneValidator {
static IDictionary<string, Regex> countryRegex =
new Dictionary<string, Regex>() {
{ "USA", new Regex("^[2-9]\\d{2}-\\d{3}-\\d{4}$")},
{ "UK", new
Regex("(^1300\\d{6}$)|(^1800|1900|1902\\d{6}$)|(^0[2|3|7|8]{1}[0-
9]{8}$)|(^13\\d{4}$)|(^04\\d{2,3}\\d{6}$)")},
{ "Netherlands", new Regex("(^\\+[0-9]{2}|^\\+[0-
9]{2}\\(0\\)|^\\(\\+[0-9]{2}\\)\\(0\\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\\-
\\s]{10}$)")},
};
public static bool IsValidNumber(string phoneNumber, string country) {
if (country != null && countryRegex.ContainsKey(country))
return countryRegex[country].IsMatch(phoneNumber);
else
return false;
}
public static IEnumerable<string> Countries {
get {
return countryRegex.Keys;
}
}
}
5.Page 43/196
Because our validation and business rules are implemented within our domain model layer, and not
within the UI layer, they will be applied and used across all scenarios within our application. We can
later change or add business rules and have all code that works with our Dinner objects honor them.
Having the flexibility to change business rules in one place, without having these changes ripple
throughout the application and UI logic, is a sign of a well-written application, and a benefit that an MVC
framework helps encourage.
6.Page 44/196
Web-based MVC frameworks map URLs to server code in a slightly different way. Instead of mapping
incoming URLs to files, they instead map URLs to methods on classes. These classes are called
“Controllers” and they are responsible for processing incoming HTTP requests, handling user input,
retrieving and saving data, and determining the response to send back to the client (display HTML,
download a file, redirect to a different URL, etc).
7.Page /196
2009年2月27日
#
2009年2月25日
#
namespace CA_CycleInvokeStaticVariable
{
using System;
class A
{
public static int X;
static A()
{
X = B.Y + 1;
}
}
class B
{
public static int Y = A.X + 1;
static B() { }
static void Main(string[] args)
{
Console.WriteLine("X = {0}, Y = {1}", A.X, B.Y);
}
}
}
//X = 1, Y = 2
