[转载]ASP.NET Web Game 架构设计1--服务器基本结构

mikel阅读(996)

[转载]ASP.NET Web Game 架构设计1–服务器基本结构 – warensoft专注于.NET – 博客园.

ASP.NET Web Game 架构设计1–服务器基本结构

1. 基 本结构图

2. 系 统组成与角色

整个系统大体上分为三个部分:1.网页客户端。2.IIS Web服务器。3.数据库及逻辑服务器。其中Web服务器不处理任何逻辑,它的 作用只有两点:1.承载用户。2.中转数据,利用ADO.NET Data Service以及调用其他的WCF,使得Web服务器成为一个数据代理服务器。

经过失败经验的论证,让IIS承载过多的逻辑,绝对是一个烂想法,应用系统应该在一开始设计的时候就彻底屏蔽这种方案,从上面图中 也不难看出来,逻辑的处理应该是一部分放在网页中使用JS来实现,另外一部分放在应用系统的逻辑服务器上实现 的。

另外,如果简单的将网页部署到IIS上,性能指标总上不去,典型的体现在要么内存占用很高,CPU上不去,要么是CPU上去了,内存又占用的太小,这样很难将服 务器的能力发挥到极致。为了应对这个问题,一个非常理想的方案是使用IIS中的WebGarden技术,可以启动多个w3wp.exe,即多个IIS服务进程。这样作的好处是将CPU资源以及内存资源均匀的分配 到多个服务进程上去,以提升服务器资源的利用效率。但是,这同样也带来了一些问题,因为要将同一个网站的资源分配到多个进程,这样内存就无法共享,再加上HTTP协议本身就是短连接,所以每次客户端发出请求的时候,都有可能被不同的服务进程所接收,这样就是导致Session无法使用,很头疼吧。为了应对这个问题,我们又需要去配置应用程序的状态服务器,说白了,就是将Session统一存储到一个服务器上,通常是将其以二进制方式存储到SQL Server中。当然,这时要求存储在Session中的数据必须是可以 串行化的。

上面说的,可以提高服务器的利用效率以外,在IIS上配置WebGarden还有什么优点呢?从上面的说明中不难 看出,因为状态是存储在统一的SQL Server中的,所以用户状态是与网站配置到哪一台Web服务器是无关的。因此,我们可以大量添加Web服务器,同时,位于不同Web服务器上的用户可以共享相同 的SQL Server状态管理,这样可以大大提高在同服、同世界的用户数量。

Web服务器,我们再来看一下应用程序的逻辑服务器和数据库服务器。这两个服务器通常在运营成本有限的情况 下,是放在同一台服务器上的(当然,能分开是最好的)。应用程序服务器一般会在某一个时间间隔下出现一个CPU使用的高峰,内存占用一般都很小,而对于SQL Server来讲,因为要提供大量的缓存,所以对于内存的消耗是比较大的。

辑服务程序,是整个系统最容易出现性能瓶颈的地方,可以使用C++或者C#来编写,然后提供一个WCFTCP方式的)的外部接口,以便Web服务器调用。值得重点强调的,无论是利用C++还是C#来编写该程序,都一定要考虑好资源释放问题(JavaC#开发人员更应该注意这一点,千万别想着什么垃圾自动 回收,很多资源是回收不了的),包括数据库连接的释放,数据结构(临时数据的储存体)的释放,以及无用线程的释放。

这次先聊到这里,在后面的BLog中我们会对整个构架中的每一个技术点进行详细说明的。如何大家需要技术支援,请给我发Email:warensoft@foxmail.com

[转载]程序员101:如何自学编程

mikel阅读(1224)

[转载]译言网 | 程序员101:如何自学编程.

你也许曾经想过要学习如何开发软件—或只是想临时的写出一个脚本—但不知道如何入手。 幸运的是,现在的互联网上到处都有丰富的学习资源让你能在短时间里成为一个程序员。

因为互联网的出现,使程序员们可以通过它讨论软件开发 技术,发布学习指导,以及共享代码实例让其他人可以在线学习。 如果你感兴趣如何才能成为一个程序员,从网上这些大量的优秀的培训资料、学习向导入手将会是个不错的开始。

首要之首:不要急于选择一种语言

新手们有一个常见的错误就是犹豫于判断哪种编程语言是 做好的、最该先学的。 我们有很多的选择,但你不能说那种语言“最好”。 我们应该理解:说到底,什么语言并不重要。 重要的是理解数据结构、控制逻辑和设计模式。 任何一种语言—甚至一种简单的脚本语言—都会具有所有编程语言都共有的各种特征,也就是说各种语言是贯通的。 我正在攻读我的计算机学学位,我编程使用Pascal,汇编,和C语言,事实上我从来没有把它当成职业以求获得回报。 我一直在自学编程,工作上用不到它,我使用现有的知识,参考各种文档和书本,学习它们的用法。 因此,不要急于选择何种编程语言。 找出你想要开发的东西,使用一种能够完成这项任务的语言,这就可以了。

根据各种开发平台的不同,有很多不同的软件开发形式可供你选择:从 网站应用到桌面软件到智能手机软件到命令行脚本工具。 这篇文章里,我将重点介绍一些很受欢迎的入门教程和资源,它们能帮助你学会如何在各种主流的平台上编程开发。 我先假设你是一个悟性很强的读者,但对于新手,当我谈论程序代码时还是要按照入门级的水平。 因为即使是你自己看一篇编程入门手册,如果发现都能理解时,心情自然会很高兴,这样利于你进一步学习。

桌面脚本

想要动手在Windows里或苹果 系统里编程,最简单的方法是从一种脚本语言或宏语言开始,例如AutoHotkey (Windows) 或 Automator (苹果系统)。 如今一些硬件程序员冲着他们的屏幕大喊大叫,说AHK和AppleScript并不是“真正”的编程语言。 也许他们说的是对的—技术上,这些种类的语言只能做一些上层的编程。 但是对于那些只是想来脱盲、想在他们的电脑里实现一些能自动运行的程序的新手来说,这些语言会是一个绝妙的入门入口—而且你会吃惊于它们丰富的功能。

例如,大家都喜爱的Texter就 是Adam使用AutoHotkey开发的能独立运行的Windows应用程序,所以说这种脚本语言远不是只能开发小规模脚本软件。 如果你想从AutoHotkey入手,可以参考Adam的指导: how to turn any action into a keyboard shortcut using AutoHotkey(然后,你可以 下载 Texter源代码 看看这个功能齐全的使用AHK开发的Windows应用程序的内部结构)。

Web开发

除了把自己约束在特定的编程语言和特定的操作系统上,你还可以在浏览器里开发你的杀 手锏程序,让它在互联网上运行,这就是webapp。 欢迎来到奇妙的web编程世界。

HTML 和 CSS: 开发网站,你第一件要知道的事情就是HTML(网页就是由它组成的)和CSS(一种让外观更好看的样式标记)。 HTML 和 CSS 并不是编程语言—它们只是页面的结构和样式信息。 然而,在开始开发web应用程序之前你必须要学会如何手工的编写简单的HTML和CSS,web页面是任何webapp的前端显示部分。 这个 HTML 指导 是你入手的好地方。

JavaScript:当你可以通过HTML和CSS构建一个静态页面后,事情就开始变得有趣了—因为到了该 学JavaScript的时候了。 JavaScript是一种web浏览器上的编程语言,它的魔力就是能在页面里制造一些动态效果。 JavaScript可以做bookmarklets, Greasemonkey 脚本, 和 Ajax, 所以它是web上各种好东西的关于因素。 学习 JavaScript从这里开

服务器端脚本:一 旦你学会了网页里的知识,你就要开始对它添加一些动态服务器操作—为了实现这些,你需要把目光转移到服务器端脚本语言,例如PHP, Python, Perl, 或 Ruby。 举个例子,如果想要制作一个网页形式的联系方式表单,根据用户的输入发送邮件,你就需要使用服务器端脚本来实现。 像PHP这样的脚本语言可以让你跟web服务器上的数据库进行沟通,所以如果你想搭建一个用户可以登录注册的网站,这样的语言正是你需要的。 Webmonkey 是一个优秀的web开发资源网站,里面有大量的各种web编程语言的指导手册。 阅读一下他们的 PHP 初学者指南。 当你感觉差不多了的时候,看看WebMonkey’s PHP and MySQL tutorial 学习如何使用PHP跟数据库交互。 网上最好的要数PHP语言官方的在线文档和函数参考了。 每个知识点上 (例如strlen function这个)都在后面列出来用户的评论注释,这些对于文档的本身是非常有价值的。 (我很喜欢PHP,但还有很多其他种服务器端的脚本语言你们都可以选择。)

Web框架:过去数年里,web开发人员在开发动态网站的过程中不得不 一遍又一遍的针对重复遇到的问题写出重复的代码。 为了避免这种每次开发一些新网站都会重复劳动一次的问题,一些程序员动手搭建了一些框架,让框架替我们完成重复性的工作。 非常流行的 Ruby on Rails 框架,作为一个例子,它利用Ruby编程语言,为我们提供了一个专门面向web的架构,普通的web应用程序都能使用它来完成。 事实上,Adam使用Rails开发了他的第一个正式的(而且是叹为观止的!)web应用程序,MixTape.me。这就是 他 的如何在没有任何经验的情况下搭建一个网站。还有一些其他的web开发框架包括 CakePHP (针对 PHP 编程者), Django (针对 Python 编程中), 以及 jQuery (针对 JavaScript).

Web APIs: API (应用层序编程接口) 是指不同的软件之间相互交换的程序途径。 例如,如果你想在你的网站上放一个动态的地图,你可以使用Google Map,而不需要开发自己的地图。 The Google Maps API 可以轻松的让你通过JavaScript在程序中引入一个地图到你的页面上。 几乎所有的现代的你所知道的和喜爱的web服务都提供了API,通过这些API你可以获取到他们的数据和小工具,在你的应用程序里就可以使用这些交互过来 的东西了,例如Twitter, Facebook, Google Docs, Google Maps, 这个列表远不止这些。 通过API把其他web应用集成到你的web应用里是现在富web开发的前沿地带。 每个优秀的主流的web服务API都附带有完整的文档和一些快速入手的指导(例如,这个就是 Twitter的)。 疯狂吧。

命令行脚本

如果你想开发一个程序,让它读取 文字或文件、输入输出一些有用的东西,那么,命令行脚本语言将是个不错的选择。 然而它并不像web应用程序和桌面应用程序那样有吸引力和好看的外观,但是作为快速开发的脚本语言,你却不能忽视它们。

很多的在 linux平台上运行的web脚本同样能以命令行模式运行,例如Perl,Python和PHP,所以如果你学会了使用它们,你将能在两种环境中使用它 们。 我的学习道路一直没离开Peal太远,我自学Python使用的是这本优秀的在线免费书Dive into Python

如果成为一个Unix高手也是你学习的目标,那么你绝对要 精通bash这个脚本语言。 Bash是Unix和Linux环境下的一种命令行脚本语言,它能够为你做所以的事情:从自动备份数据库脚本到功能齐全的用户交互程序。 起初我没有任何使用bash脚本的经验,但最终我用bash开发了一个全功能的个人代办任务管理器: Todo.txt CLI

插件(Add-ons)

如今的web应用程序和浏览器都可以通过一些扩展软件来丰 富自己的功能。 由于一些现有的软件,例如Firefox、WordPress越来越受到开发人员的关注,插件的开发也日益流行,人们都在说“But if only it could do THIS…”

只要你掌握了HTML,JavaScript和CSS,你就可以在任何的浏览器里 开发你想要的很多东西。 Bookmarklets, Greasemonkey user scripts, 和 Stylish user styles这些软件都是用的更普通页面一样的语言写成的, 这几个东西都值得你去研究一些。

更高级的浏览器扩展程序,例如 Firefox的扩展,它们可以帮助你很多。 开发Firefox的扩展,举个例子,需要你精通JavaScript和XML(一种标记语言,类似HTML,但具有更严格的格式)。 早在2007年我就写下来 how to build a Firefox extension, 这是我在笨手笨脚的研究网上的一些学习资料后获得的成果。

很多 免费的、受欢迎的web应用程序都提供了扩展框架,例如WordPress 和 MediaWiki。 这些应用程序都是用PHP写成的,所以只有对PHP熟悉你才能做这些事情。 这个就是 如何编写WordPress插件。 而想驾驭Google Wave前沿技术的开发人员可以从使用HTML, JavaScript, Java, 和 Python 写小组件和小工具开始。 我写的第一个Wave bot是跟着这个 一 个下午时间的快速入门指导开始的。

开 发桌面上的Web应用程序

学习编程最好的结果是你在一个环境下学的东西可以应用到另外的环境中。 先学习开发web应用程序的好处就是我们有一些方法可以让web应用程序直接在桌面上运行。 例如, Adobe AIR 是一个跨平台的即时运行平台,它能让你编写的程序运行在任何装有AIR的操作系统的桌面上。 AIR应用程序都是由HTML, Flash, 或 Flex 写成的,所以它能让你的web程序在桌面环境中运行。 AIR是开发部署桌面应用程序的一个优秀的选择,就像我们提到过的 10 个让你值得去安装AIR的应用程序

移 动应用开发

能在iPhone或者Android智能手机上运行的手机应用程序的开发如今正呈现井喷之势,所以你也可以梦想一下如何在 iTunes应用商店里通过你的天才程序大赚一笔。 但是,作为一个编码新手,直接奔向移动开发所经历的学习曲线可能会很陡,因为它需要你熟悉高级的编程语言,例如Java和Objective C。 然而,你当然应该看看iPhone 和 Android 编程究竟是什么样子的。 阅读这个 简 单的iPhone应用开发例子 可以初步认识一下iPhone程序的开发过程。 Android 程序都是由Java写成的,这有一个 简单的视频教程教你如何开发第一个”Hello Android“程序(注:可能需要代理才能看这个视频)。

耐心,刻苦,尝试,失败

好的程序员都有一个不达目的誓不罢休的品质,他们会惊喜于通过长期推敲 和失败换来的一点成绩。 学会编程会有很好的回报的,但是学习的过程可能会是饱受挫折和孤独的。 如果有可能,最好找个伴一起陪你做这件事。 想精通编程,这和其他事情一样,需要坚持,反复尝试,获得更多的经验。

这篇文章里的内容就是对那些想通过自我研究达到学会编程目的的新手 们的一些重要建议。 编程老手们:我有什么遗漏吗? 不论你的水平如何,请留下你的想法。

[转载]MVC SQL Site Map Provider - CodeProject

mikel阅读(1203)

[转载]MVC SQL Site Map Provider – CodeProject.

Introduction

I’m developing my first MVC application. I’ve been working with ASP.NET for a couple of years, and only now have I got some contact with MVC.

First of all, I’ve defined the application layout and I realized that I needed to display the menu and the site map path dynamically. After some research, I couldn’t find any SQL site map provider for MVC. The only sample that I found was the MVCSiteMapProvider posted by Maarten Balliauw, and it has XML as the data source. With this sample, I’ve developed the MVCSQLSiteMapProvider. This is only a prototype, and it could be improved. I’ve only implemented the base functionalities so far. So, if you have any suggestions, just write them down.

Using the code

The site map data model is similar to the XML site map provider. So, it’s possible to define a node with the corresponding URL or with the controller/action.

Database.png

The site map provider class inherits from the StaticSiteMapProvider and, as I said before, I’ve only implemented what I needed so far.

Collapse
public class MvcSQLSitemapProvider : StaticSiteMapProvider
{
    private const string _errormsg1 = "Missing node ID";
    private const string _errormsg2 = "MDuplicate node ID";
    private const string _errormsg3 = "Missing parent ID";
    private const string _errormsg4 = "Invalid parent ID";
    private const string _errormsg5 = "Empty or missing connection string";
    private const string _errormsg6 = "Missing connection string";
    private const string _errormsg7 = "Empty connection string";
    private string _connect = String.Empty;
    private Dictionary _nodes = new Dictionary(16);
    private SiteMapNode _root;
    public override void Initialize(string name, NameValueCollection attributes)
    {
        if (attributes == null)
            throw new ArgumentNullException("attributes");
        if (string.IsNullOrEmpty(name))
            name = "MvcSitemapProvider";
        if (string.IsNullOrEmpty(attributes["description"]))
        {
            attributes.Remove("description");
            attributes.Add("description", "MVC site map provider");
        }
        base.Initialize(name, attributes);
        string connect = attributes["connectionStringName"];
        if (string.IsNullOrEmpty(connect))
            throw new ProviderException(_errormsg5);
        attributes.Remove("connectionStringName");
        if (WebConfigurationManager.ConnectionStrings[connect] == null)
            throw new ProviderException(_errormsg6);
        _connect = WebConfigurationManager.ConnectionStrings[connect].ConnectionString;
        if (string.IsNullOrEmpty(_connect))
            throw new ProviderException(_errormsg7);
        if (attributes.Count > 0)
        {
            string attr = attributes.GetKey(0);
            if (!string.IsNullOrEmpty(attr))
                throw new ProviderException(string.Format(
                  "Unrecognized attribute: {0}", attr));
        }
    }
    public override SiteMapNode BuildSiteMap()
    {
        lock (this)
        {
            if (_root != null)
                return _root;
            SiteMapContextDataContext db = new SiteMapContextDataContext(_connect);
            var siteMpaQuery = from s in db.SITEMAPs
                               orderby s.ID
                               select s;
            foreach (var item in siteMpaQuery)
            {
                if (item.Equals(siteMpaQuery.First()))
                {
                    _root = CreateSiteMapFromRow(item);
                    AddNode(_root, null);
                }
                else
                {
                    SiteMapNode node = CreateSiteMapFromRow(item);
                    AddNode(node, GetParentNodeFromNode(item));
                }
            }
            return _root;
        }
    }
    private SiteMapNode CreateSiteMapFromRow(SITEMAP item)
    {
        if (_nodes.ContainsKey(item.ID))
            throw new ProviderException(_errormsg2);
        SiteMapNode node = new SiteMapNode(this, item.ID);
        if (!string.IsNullOrEmpty(item.URL))
        {
            node.Title = string.IsNullOrEmpty(item.TITLE) ? null : item.TITLE;
            node.Description = 
             string.IsNullOrEmpty(item.DESCRIPTION) ? null : item.DESCRIPTION;
            node.Url = string.IsNullOrEmpty(item.URL) ? null : item.URL;
        }
        else
        {
            node.Title = string.IsNullOrEmpty(item.TITLE) ? null : item.TITLE;
            node.Description = 
             string.IsNullOrEmpty(item.DESCRIPTION) ? null : item.DESCRIPTION;
            IDictionary routeValues = new Dictionary();
            if (string.IsNullOrEmpty(item.CONTROLLER))
                routeValues.Add("controller", "Home");
            else
                routeValues.Add("controller", item.CONTROLLER);
            if (string.IsNullOrEmpty(item.CONTROLLER))
                routeValues.Add("action", "Index");
            else
                routeValues.Add("action", item.ACTION);
            if (!string.IsNullOrEmpty(item.PARAMID))
                routeValues.Add("id", item.PARAMID);
            HttpContextWrapper httpContext = new HttpContextWrapper(HttpContext.Current);
            RouteData routeData = RouteTable.Routes.GetRouteData(httpContext);
            if (routeData != null)
            {
                VirtualPathData virtualPath = routeData.Route.GetVirtualPath(
                  new RequestContext(httpContext, routeData), 
                  new RouteValueDictionary(routeValues));
                if (virtualPath != null)
                {
                    node.Url = "~/" + virtualPath.VirtualPath;
                }
            }
        }
        _nodes.Add(item.ID, node);
        return node;
    }
    private SiteMapNode GetParentNodeFromNode(SITEMAP item)
    {
        if (!_nodes.ContainsKey(item.PARENT_ID))
            throw new ProviderException(_errormsg4);
        return _nodes[item.PARENT_ID];
    }
    protected override SiteMapNode GetRootNodeCore()
    {
        return BuildSiteMap();
    }
}

I’ve also created three user controls. The first one is used to display the main menu. It retrieves all the root child nodes and displays them.

Menu.png

The second one retrieves the site map path to the current page.

SiteMapPath.png

The last control is used to display the content menu, which retrieves all the current child nodes.

ContentMenu.png

These controls are very simple and I didn’t take much time on making them good looking. Smile

Well, I hope this post was useful.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

TODODotNet

[转载]自定义SiteMapProvider——实现StaticSiteMapProvider

mikel阅读(1084)

[转载]自定义SiteMapProvider——实现StaticSiteMapProvider « Shander Lam’s Blog.

在创建站点地图的时候,ASP.NET默认使用XmlSiteMapProvider,并使用web.sitemap文件作为数据源。如果我们 想根据数据库中的数据来动态地生成站点地图,我们可以通过实现StaticSiteMapProvider或者SiteMapProvider抽象类来自 定义一个SiteMapProvider。StaticSiteMapProvider继承于SiteMapProvider,并且是 XmlSiteMapProvider的基类。如果只是更改站点地图的数据源,我们只需要实现StaticSiteMapProvider抽象类即可。

首先创建一个名为MySiteMapProvider的类继承StaticSiteMapProvider。然后为这个类增加以下修饰:

[AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
public class MySiteMapProvider : StaticSiteMapProvider

System.Security.Permissions.SecurityAction.Demand表示要求调用堆栈中的所有高级调用方都已被 授予了当前权限对象所指定的权限,而Level = AspNetHostingPermissionLevel.Minimal则指明了许可级别为最小。

在MySiteMapProvider类中,为了能够自定义RootNode,需要声明一个私有的SiteMapNode类型变量rootNode 用来保存根节点的值。除此之外,还需要重写RootNode属性使其与rootNode变量关联,代码如下:

private SiteMapNode rootNode = null;// Return the root node of the current site map.
public override SiteMapNode RootNode
{
get
{
SiteMapNode temp = null;
temp = BuildSiteMap();
return temp;
}
}

为了在执行Clear函数时能将rootNode变量清空,我们还需重写Clear函数,代码如下:

// SiteMapProvider and StaticSiteMapProvider methods that this derived class must override.
// Clean up any collections or other state that an instance of this may hold.
protected override void Clear()
{
lock (this)
{
rootNode = null;
base.Clear();
}
}

上述代码加lock块是为了防止调用函数时其他线程调用该资源,引发错误。

此外,StaticSiteMapProvider抽象类有两个必须实现的函数,GetRootNodeCore和BuildSiteMap。其中 GetRootNodeCore用于获取根节点,BuildSiteMap用于从持久性存储区加载站点地图信息,并在内存中构建它。以下是简单的实现代码:

public override SiteMapNode BuildSiteMap()
{
// Since the SiteMap class is static, make sure that it is
// not modified while the site map is built.
lock (this)
{
// If there is no root node, then there is no site map.
if (null == rootNode)
{
// Start with a clean slate
Clear();
rootNode = new SiteMapNode(this, “home”, “/Home”, “Home”);
SiteMapNode aboutNode = new SiteMapNode(this, “about”, “/Home/About”, “About”);
AddNode(aboutNode, rootNode);
SiteMapNode designNode = new SiteMapNode(this, “design”, “/Design”, “Design”);
AddNode(designNode, rootNode);
SiteMapNode artistNode = new SiteMapNode(this, “artist”, “/Artist”, “Artist”);
AddNode(artistNode, rootNode);
SiteMapNode videoNode = new SiteMapNode(this, “video”, “/Video”, “Video”);
AddNode(videoNode, rootNode);
SiteMapNode bookNode = new SiteMapNode(this, “book”, “/Book”, “Book”);
AddNode(bookNode, rootNode);
}
return rootNode;
}
}protected override SiteMapNode GetRootNodeCore()
{
return RootNode;
}

上述代码中由于线程的安全性问题,因此要在BuildSiteMap方法中增加lock块,以确保在执行BuildSiteMap方法时,其他线程 不能访问相应的资源。如果要使SiteMap中的节点数据来自数据库,则在BuildSiteMap方法中加入数据库访问逻辑即可。

[转载]Sitemaps.NET

mikel阅读(1146)

[转载]Sitemaps.NET – James Newton-King.

Sitemaps.NET is a website plugin that automatically generates an XML sitemap of your content. Sitemaps.NET reuses a site’s existing ASP.NET sitemap and automatically mirrors changes in your site to search engines.

Sitemaps.NET CodePlex Project

Sitemaps.NET Download

Features

  • Quickly generate XML sitemaps for search engines
  • Integrates with the ASP.NET sitemap functionality, automatically mirrors changes to search engines
  • Specify the priority and update frequency of content within your site on a page by page basis.
  • Simple plug in installation

Installation

  1. Extract Newtonsoft.Sitemaps.dll from the archive’s /bin directory into your own applications.
  2. Add the SitemapHandler to your web.config’s httpHandler section.
    <add verb="*" path="sitemap.axd" type="Newtonsoft.Sitemaps.SitemapHandler, Newtonsoft.Sitemaps"/>

    The path will determine the URL you submit to search engines. In the example above, for this site, the generated XML would be accessed with the URL http://www.newtonsoft.com/sitemap.axd.

  3. That’s it. Now let search engines know about your sitemap file. Instructions can be found here. If you want to submit your sitemap directly to Google, login with your Google account here and submit the URL to the sitemap XML.

Arguments

These querystring arguments are passed to search engines when submitting the URL to your sitemap.

formatting The written XML format. This value is constrained by the Formatting enum. Default value is Indented.

  • Indented
  • None
useFileModifiedDate If a SiteMapNode doesn’t have a lastmod date and this option is true then Sitemaps.NET will attempt to get the lastmod date from the physical file. Default value is false.

SiteMapNode Element Options

In addition to defining a list of the URL’s that make up your website, you can also supply metadata to search engines about each page. This metadata is define in your web.sitemap file against a SiteMapNode.

lastmod The date of last modification of the file. This can be any valid DateTime string.
changefreq How frequently the page is likely to change. This value is constrained by the ChangeFrequency enum.

  • Always
  • Hourly
  • Daily
  • Weekly
  • Monthly
  • Yearly
  • Never
priority A decimal indicating priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0. The default priority of a page is 0.5.

Below is an example SiteMapNode from the web.sitemap file.

<siteMapNode url="~/products/sitemaps/quickstart.aspx"
    title="Quickstart guide" priority="0.5" lastmod="12/12/2005"
    changefreq="Monthly"/>

[转载]ASP.NET崩溃 - SiteMap里的疯狂循环(概译)

mikel阅读(950)

[转载]ASP.NET崩溃 – SiteMap里的疯狂循环(概译) – 维生素C.net – 博客园.

作者:tess
原文地址:ASP.NET Crash – Crazy looping in a SiteMap

本文只是一个快速的概括性翻译, 如果敢兴趣还请您看原版.

我想快速创建一个并不美观的站点地图(site map), 所以我只简单的在我override的BuildSiteMap()函数里使用一个小循环添加了几个地图节点(sitemap node)

public override SiteMapNode BuildSiteMap(){
for (int i = 0; i < 5; i++)
myRoot.ChildNodes.Add(
new SiteMapNode(this, i.ToString(), i.ToString(), i.ToString()));
return myRoot;
}

当我运行这个web应用程序的时候我得到的却是”堆栈溢出(Stack overflow)”,然后服务器就崩溃了. 然后我借助调试器调试这段代码,我所看到的东西非常奇怪:

1) int i = 0
2) i < 5
3) myRoot
4) int i = 0
5) i < 5
etc.

看起来i的值并没有增加,是编译器的bug还是CLR的?(暂时撇开sitemap的内部机制, 因为sitemap从设计上不允许我们这么使用,但是这个条语句你却可以随便写的)

Debug之前我们向后退几步重审一下:

  1. 堆栈溢出
  2. 一个看起来像是无尽的循环

造成堆栈溢出是因为我们已经占用了大量的内存,而它们是当初为了在栈上分配太多的指向指向局部变量或参数的指针而服务的.(we have exceeded the amount of memory reserved for the stack by allocating too many function pointers, pointers to local vars and parameters on the stack.)但是往往我们都是因为死循环(never-ending recursion)而造成的, 换言之, funcitonA()调用了functionB(),而functionB()里又调用了functionA().

void MyRecursiveFunction(){
for(int i=0; i<5; i++){
–> MyRecursiveFunction();
}

}

所以此时我们的调用栈(callstack)看起来应该是这样的:

functionB()
functionA()
functionB()
functionA()

好,那我们现在想象一下如果你现在有这样的函数:

当你第一次在断点位置上停止的时候i的值应该是0,调用栈看起来应该是

MyRecursiveFunction()

现在我们用另一种方式执行进入函数内部(其实还是它本身)

for(int i=0; i<5; i++){
for(int i2=0; i2<5; i2++){
for(int i3=0; i3<5; i3++){
for(int i4=0; i4<5; i4++){
for(int i5=0; i5<5; i5++){
for(int i6=0; i6<5; i6++){
for(int i7=0; i7<5; i7++){

}
}
}
}
}
}
}

所以调用栈应该是这样的:

MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()
MyRecursiveFunction()

调试:

将windbg附属到w3wp.exe的进程上(文件/附属到进程),按下g运行.程序一会就终止了显示出了下列信息,表明是堆栈溢出(就 像我们已经知道的一样)

(7e4.ddc): Stack overflow - code c00000fd (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0fa4235c ebx=02beca74 ecx=02beca74 edx=02becb54 esi=02becb54 edi=02beca74
eip=686b5cb4 esp=02163000 ebp=02163004 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210246
System_Web_ni+0xf5cb4:
686b5cb4 56 push esi

如果我们用!clrstack看一下堆栈来确定我们是怎么结束的,我们只能看到这个:

0:016> !clrstack
OS Thread Id: 0xddc (16)
ESP EIP 
02163000 686b5cb4 System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode)

可惜的这些不能告诉我们更多的东西, 当我们陷入堆栈溢出错误的时候!clrstack有时会在列举堆栈信息上出现一些问题,所以我们必须使用!dumpstack来看一下.
(注 意:!dumpstack不展示真实的堆栈,有一些函数可能是错误的,但是它能很好的让我们知道究竟怎么了)

0:016> !dumpstack
OS Thread Id: 0xddc (16)
Current frame: (MethodDesc 0x68b03720 +0x4 System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
ChildEBP RetAddr Caller,Callee
02163004 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
0216300c 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
0216303c 686b5cdf (MethodDesc 0x68b03720 +0x2f System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
02163074 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
0216307c 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
021630ac 686b5cdf (MethodDesc 0x68b03720 +0x2f System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
021630e4 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
021630ec 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
0216311c 686b5cdf (MethodDesc 0x68b03720 +0x2f System.Web.StaticSiteMapProvider.GetChildNodes(System.Web.SiteMapNode))
02163154 686b1fc4 (MethodDesc 0x68aeff30 +0x18 System.Web.SiteMapNode.get_ChildNodes())
0216315c 0f765641 (MethodDesc 0xfa42328 +0x59 ViewSiteMapProvider.BuildSiteMap())
...

Ok,看起来问题出在ChildNodes属性上了, 它调用GetChildNodes()函数,而GetChildNodes()又再次调用我们的BuildSiteMap函数, 该函数调用了ChildNodes属性, 所以这样造成一个死循环.

结论:

创建站点地图一文中你可以找到答案和解决文章开始时问题的正确处理方法.

1

[转载]让你的Asp.Net网站自动生成Sitemap——XmlSitemap - SkyD - 斯克迪亚个人博客 - 博客园

mikel阅读(999)

[转载]让你的Asp.Net网站自动生成Sitemap——XmlSitemap – SkyD – 斯克迪亚个人博客 – 博客园.

首先我要说明:ASP.NET内置的Sitemap与这里讲的Sitemap是完全不同的,ASP.NET中的Sitemap主要用于给用户导航, 而这里说的Sitemap是用来给搜索引擎爬虫指路。

还是直接来看看官方解释吧:

什么是 Sitemap?

Sitemap 可方便管理员通知搜索引擎他们网站上有哪些可供抓取的网页。最简单的 Sitepmap 形式,就是 XML 文件,在其中列出网站中的网址以及关于每个网址的其他元数据(上次更新的时间、更改的频率以及相对于网站上其他网址的重要程度为何等),以便搜索引擎可以 更加智能地抓取网站。

网络抓取工具通常会通过网站内部和其他网站上的链接 查找网页。Sitemap 会提供此数据以便允许支持 Sitemap 的抓取工具抓取 Sitemap 提供的所有网址,并了解使用相关元数据的网址。使用 Sitemap 协 议并不能保证网页会包含在搜索引擎中,但可向网络抓取工具提供一些提示以便它们更有 效地抓取网站。

Sitemap 0.90 是依据创意 公用授权-相同方式共享 (Attribution-ShareAlike Creative Commons License) 的条款提供的,并被广泛采用,受 Google、Yahoo! 和 Microsoft 在内的众多厂商的支持。

引 自Sitemaps.org:http://www.sitemaps.org/zh_CN/

综上所述,提供Sitemap是辅助搜索引擎爬虫收录网站的一种手段,没有Sitemap你的网站一样会被收录,而有 了Sitemap则会被收录的更全面、准确。

它除了提供网址外,最重要的就是提供了页面的更新时间戳,以及 网站侧重点和更新回访频率建议,使得搜索引擎能更精确地把握你的网站。

如何实现自动生成Sitemap?

现成的生成器已有不少:

http://code.google.com/p/sitemap-generators/wiki/SitemapGenerators

http://www.google.com/support/webmasters/bin/answer.py?answer=34634

不过在Asp.Net中,没有官方的生成工具,搜索“Asp.Net Sitemap”找到的也都是大把的Asp.Net内置的Sitemap功能介绍网页。

故此,我希望自己来实现一个Asp.Net的 Sitemap生成工具。并且我希望这个工具是可以和Asp.Net同步交互进行数据更新的,以保障数据的时效性;而其他大多数生成器都像是一个私人爬 虫,你需要手动放出它来爬遍你的网站,以生成整站的Sitemap,我不喜欢这样。

XmlSitemap

这就是我实现的Sitemap生成工具,简单讲一下实现方式:

  1. 通过数据库存储站点、页面集合、页面数据:
    image
  2. 在Asp.Net网站中,增删改数据时,调用站点地 图公开的方法更新数据库数据。
  3. 通过Ashx输出XML格式的Sitemap供搜索引擎爬虫读取。

在文 章末尾处我将共享此项目的下载链接,接下来将讲一下此项目的使用方法。

如何部署?

我 将提供以下文件用于在现有Asp.Net网站中部署此功能:

image

首先要引用XmlSitemap.dll。

然 后通过“添加现有项”将XMLSiteMap.ashx.cs及XMLSiteMap.ashx添加到项目中。

再通过“添加现有项”将 SiteMap.mdf添加到项目的App_Data目录中。

在Web.Config中指定SiteMap.mdf的数据库连接字串:

<connectionStrings>

<add name=“MySitemapDataConnstr” connectionString=“Data Source=.\SQLEXPRESS;AttachDbFilename=’C:\Users\SkyD\Documents\Visual Studio 2008\Projects\实验室\WebApplication10\WebApplication10\App_Data\SiteMap.mdf’;Integrated Security=True;User Instance=True”/>

</connectionStrings>

在项目中新增一个Global.asax文件(如果之前没创建此文件的话),在其 Application_Start中进行初始化:

image

其中蓝色高亮部分是上文中在Web.Config中指定 的SiteMap.mdf的数据库连接字串;

黄色高亮部分是你的网站名称,在每次提交数据时都将用到此字符串;

绿色高亮 部分是你的这个站点的网址,每次新增的网址数据都必须位于此网址域名下。

如何使用?

我 们将通过一个按钮来模拟添加数据的操作:

protected void Button1_Click(object sender, EventArgs e)

{

var id=Guid.NewGuid();

站点地图.添加页面(“MySite”, id, Path.Combine(“http://www.MySite.com/”, “Page.aspx?ID=” + id), 0.5, 更新频率.每天);

}

注意:这里仅仅是用来测试,所以临时生成了一个Guid传入站点地图,而在实 际使用时,应当以你的原数据条目的Guid传入,因为你在之后很可能还会对其进行更新、删除操作,如果同时要反映到站点地图中的话,你就必须还以它的 Guid作为标识,才能找到它。

当你频繁点击这个按钮后,站点地图中就会新增了多条数据,你可以通过访问 XmlSiteMap.ashx?Site=MySite查看当前的页面集合列表:

image

其中的Url地址是页面集合的网址,由于页面数据量没有 达到页面集合所容纳的上限,所以目前就只有一个页面集合。

访问页面集合的网址:

image

这里就是每个页面的详细地址及相关信 息列表。

除了添加数据之外,还有更新、删除等方法,由于都是中文写的代码,易于理解,就不在此一一演示了:

image

资源下载

部署文件:http://www.uushare.com/user/icesee/file/1893271

示例网站项目源代码:http://www.uushare.com/user/icesee/file/1893269

XmlSitemap源代码:http://www.uushare.com/user/icesee/file/1893270

本文的XPS版本:http://www.uushare.com/user/icesee/file/1895946

[转载].Net下如何跨语言调用Delphi写的报表引擎

mikel阅读(1120)

[转载].Net下如何跨语言调用Delphi写的报表引擎 – 周金根 – 博客园.

我去年上半年之前一直使用的是Delphi,公司在这上面也积累了很多公共资源。在06年9月实现了一个功能强大的报表引擎,公司到现在基本每 个项目组都在使用它做报表。现在在.Net下,使用OpenExpressApp, 暂时也没有足够精力去重新开发一个报表引擎(OpenReport),所以就想到先重用以前的报表引擎。

下面就介绍一下如何在WPF中使用Delphi下的功能。

封装Delphi引擎为一个OCX控件

之前的报表引擎是基于Delphi下的,在跨语言应用下,最容易想到的就是使用ActiveX,于是使用Delphi做了一个 ActiveXForm,封装了一个OCX控件并注册,名称为【ReportFram.ocx】,这里就不详细介绍具体生成过程了。

在.Net中使用

.Net下的控件都是从Control继承下来的,要想使用OCX控件,就需要在OCX和Control之间适配一下。Delphi封装的 OCX本身并不知道如何在.Net下使用,我们可以通过以下步骤,由VS给我们自动生成一个适配程序集。

  1. 在Toolbox中添加一项
  2. 新建一个Window Application,把ReportFramX Control拖入到一个Form上,这时你可以看到Solution Explorer的项目下自动生成了两个dll:ReportFram.dll和AcReportFram.dll。这是VS生成,应该会有命令可以生 成,没有细查。
  3. 在WPF下使用AxReportFramX
    使用WindowsFormsHost控件使用Win下的Control,Xaml如下所示:

    <Grid><br>        <WindowsFormsHost Name="windowsFormsHost1" /><br>    </Grid><br>

    代码如下:

            public Window1()         {             InitializeComponent();             var rptFram = new AxReportFram.AxReportFramX();             windowsFormsHost1.Child = rptFram;         } 

    运行界面如下:

[转载]JIRA破解版下载

mikel阅读(1077)

[转载]JIRA破解版真难找。终于还是找到了。呵。。。。 – 又是一年,新的项目筹划ing… – 博客园.

JIRA是一个优秀的问题(or bugs,task,improvement,new feature )跟踪及管理软件。
它由Atlassian开发,采用J2EE技术.它正被广泛的开源软件组织,以及全球著名的软件公司使用,它堪称是J2EE的Bugzilla。

JIRA提供了全面的功能,界面十分友好,可用性以及可扩展性方面都十分出色,如果购买商业版许可,还可以得到JIRA的源码(在开发许可协议下可以定制 自己的JIRA系统)。

organisation  *****@Cracked By martin.xus@gmail.com
Date Purchased  28/四月/06
License Type  JIRA Enterprise: Commercial Server
License ID  BABQW
Support Period  Your commercial JIRA support and updates are available until 03/九月/43.

JIRA 3.6 下载:
http://www.atlassian.com/software/jira/downloads/binary/atlassian-jira-enterprise-3.6-standalone.zip

地址已更新:

下载(请将rar中的文件释放下来,直接覆盖掉web-inf下面的包即可,适用版本3.6):
http://www.blogjava.net/Files/martinx/atlassian-extras-0.7.19.rar

破解jira的License。只是把classes反编译过来,修改一下。效果如下,License的类型为JIRA Enterprise: Commercial Server。

//要让程序能找到这个包。atlassian-extras-0.7.19.jar

import com.atlassian.license.LicensePair;
import java.io.*;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;

public class keygen
{

public keygen()
{
}


public static void main(String args[])
throws IOException
{
try
{
long l = 267L;
long l1 = System.currentTimeMillis();
long l2 = System.currentTimeMillis();
String s
= “”;
System.out.println(”Keygen
for JIRA Enterprise Edition.”);
System.out.print(”created by mydaj[ROR].”);
do
{
System.out.print(”\nEnter your organization name: “);
for(int i = System.in.read(); i != 10 && i != 13; i = System.in.read())
s
= s + (char)i;

}
while(s == “”);
try
{
PKCS8EncodedKeySpec pkcs8encodedkeyspec
= new PKCS8EncodedKeySpec(EncodedPrvKey);
KeyFactory keyfactory
= KeyFactory.getInstance(”DSA”, “SUN”);
java.security.PrivateKey privatekey
= keyfactory.generatePrivate(pkcs8encodedkeyspec);
String s1
= Long.toString(l, 10);
s1
= s1 +^^”;
s1
= s1 + Long.toString(l1, 10);
s1
= s1 +^^”;
s1
= s1 + Long.toString(l2, 10);
s1
= s1 +^^”;
s1
= s1 + s;
byte abyte0[] = s1.getBytes();
Signature signature
= Signature.getInstance(”SHA1withDSA”);
signature.initSign(privatekey);
signature.update(abyte0);
byte abyte1[] = signature.sign();
LicensePair licensepair
= null;
try
{
licensepair
= new LicensePair(abyte0, abyte1);
}

catch(Exception exception1)
{
exception1.printStackTrace();
}

System.out.println(s1);
System.out.println(”Your license key is: “);
System.out.println(licensepair.toString());
}

catch(Exception exception)
{
exception.printStackTrace();
}

}

catch(IOException ioexception) { }
}


static byte EncodedPrvKey[] = {
48, 126, 1, 75, 2, 1, 0, 48, 126, 1,
44, 6, 7, 42, 122, 72, 50, 56, 4, 1,
48, 126, 1, 31, 2, 127, 127, 0, 3, 127,
83, 127, 29, 117, 18, 41, 82, 33, 74, 100,
46, 20, 28, 25, 10, 17, 73, 82, 60, 17,
68, 0, 61, 30, 63, 128, 74, 81, 38, 105,
69, 93, 64, 34, 81, 5, 89, 61, 115, 88,
6, 65, 59, 11, 70, 48, 10, 53, 101, 85,
108, 41, 127, 59, 128, 29, 52, 111, 14, 102,
96, 73, 107, 103, 80, 91, 92, 97, 97, 24,
4, 123, 16, 34, 62, 79, 69, 87, 41, 2,
73, 58, 27, 8, 59, 87, 25, 58, 88, 90,
21, 15, 4, 5, 125, 10, 45, 59, 30, 61,
2, 53, 84, 19, 90, 22, 111, 50, 10, 117,
13, 82, 43, 97, 41, 42, 17, 14, 34, 3,
25, 99, 47, 72, 1, 57, 2, 21, 0, 105,
96, 80, 113, 21, 35, 11, 52, 78, 110, 71,
126, 94, 21, 124, 11, 16, 88, 28, 11, 2,
127, 127, 0, 9, 31, 96, 123, 42, 101, 61,
34, 53, 68, 85, 92, 54, 72, 87, 71, 121,
108, 81, 69, 6, 58, 22, 126, 7, 87, 76,
11, 61, 7, 126, 103, 81, 89, 87, 114, 70,
44, 89, 79, 26, 113, 7, 16, 127, 128, 76,
73, 22, 113, 35, 24, 76, 40, 22, 19, 73,
49, 9, 50, 116, 56, 90, 31, 60, 22, 122,
117, 84, 124, 115, 40, 32, 93, 82, 30, 43,
77, 90, 117, 111, 110, 93, 127, 11, 6, 33,
53, 98, 15, 5, 98, 122, 1, 36, 59, 52,
92, 15, 66, 88, 81, 112, 119, 88, 125, 33,
31, 90, 27, 97, 6, 110, 117, 102, 94, 128,
123, 85, 37, 100, 1, 76, 59, 2, 49, 73,
42, 4, 22, 2, 20, 42, 50, 88, 30, 125,
37, 118, 50, 20, 82, 63, 0, 8, 36, 106,
9, 110, 124, 107, 68
}
;

}

[转载]初次体验Android,过程很艰辛!

mikel阅读(1115)

[转载]初次体验Android,过程很艰辛! – Mr.d’s Time – 博客园.

在iphone与Android之间,最终还是选择玩玩Android,很激动,第一次玩手机编程,过程充满着惊喜与小小的愤怒。

安装篇

Android的开发的语言是Java或C,因此我选择了Java;

1、下载并安装JDK(5或6)[设置 JDK,Bin的环境变量]

2、下载并安装Eclipse Classic版本

3、安装ADT

根据官方文档描叙,应该是很轻松的、很快感的,但我在此步骤中耗费了1-2个小时,直到最后天真的认为是软件版本问题或啥安装步骤乱了,网上搜了半 天,问题依然没有解决,最后还是不太相信这样的结果。为什么这样了,那就是感谢国家,感谢防火墙之父,在线安装ADT的小道被堵了。值得高兴的是开发环境 支持代理。于是爬上墙顶了。设置图(安装后会重启):

4、下载并安装Android SDK

>>这个玩意儿的下载也需要爬到墙顶,设置图:

>>[设置Tools的环境变量]

>>设置Eclipse的Android SDK Local:这是你Android SDK所在的目录,设置图:

5、建立个AVD

通过Eclipse下的windows菜单–Android SDK And AVD Manager新建立一个AVD;

开发篇

通过上面的安装篇,如果顺利,那么恭喜您,您离手机编程有靠近一步步了,吼吼,根据通用惯例,Hello World大行其道。

步骤就不详细的介绍了,相信大家对这东西如流水般,哗啦啦的搞定。但 值的注意的:运行的时候请耐心等待,由于本人心急吃热豆腐的心态,导致很多次没运行成功(还没出来就认为出现错误了,于是就用2.0开发、 2.1开发)最后在没有关闭模拟器的情况下,跑了趟WC,回来看到满意的效果,神了~~~。

总结

初次体验Android,很折腾,但值的您折腾,大伙您看了,心动了么,心动不如行动昂。