ASP.NET MVC 框架入门——写一个搜索引擎

ASP.NET MVC 框架入门——写一个搜索引擎

 

动态网页的历史非常悠久,可以追溯到上个世纪。就技术类型而言,主要有ASPPHPJSP三大派。笔者接触过ASPPHP,遗憾的是几乎从未接触过JSP。偶就天生不是JAVA语系的。

 

后来,笔者稍微远离了一下Web开发,Web发生了翻天覆地的变化,css成了布局主流,ASP.NET冒出来了。这使得笔者不得不在20082009年间重新进入Web开发领域。然后,自认为已经跟上时代了,于是又稍微远离了Web开发。短短两三年,PHP几乎啥也没变,HTML基本未变(虽然冒出了个HTML5),但ASP.NET却发生了翻天覆地的变化:官方MVC框架的推出,使得ASP.NET再也不用使用很别扭的服务端控件了,将自由操控HTML的权利还给了开发者(然而,却剥夺了自由操控URL的权利)。

 

下面,笔者以写一个搜索引擎为例,带大家进入ASP MVC 框架的世界。

 

建立项目

如下图,在VS2012中建立一个ASP.NET MVC4 Web Application

image

 

然后选Basic吧:

image

 

试图引擎按默认选择Razor吧。

 

建好之后,我们将看到如下的项目结构:

 

其中Views放各种页面,Contentcss啥的,Controllers放“控制器”代码,Models里放各种业务模型的数据结构定义。

image

URL规划

这个MVC框架的一个越俎代庖的事情就是接管了URL路由。嗯,其实也蛮方便的,叫越俎代庖有点过了,仁者见仁智者见智吧。

 

打开RouteConfig.cs,我肯可以看到:

 

public class RouteConfig

{

    public static void RegisterRoutes(RouteCollection routes)

    {

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

        routes.MapRoute(

            name: "Default",

            url: "{controller}/{action}/{id}",

            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

        );

    }

}

 

这里有个默认的路由。比如一段http://www.xxx.com/a/b/c/,按照这个route的解释,a就是controller的名字,b就是action的名字,c就是id的名字。如果访问http://www.xxx.com/a/,那么acontroller的名字,actionid未给出,就按照default中的设定,actionIndexid为空。

 

说到这里,还没解释action是啥,id是啥呢。按照我们很久以前的url规划习惯,经常有article.aspx?action=modify&id=1这样子的urlcontroller的概念就是这里的acticle.aspx,表示文章处理的页面/模块;action就是urlquery string中的action,一个处理模块通常由多个功能,action参数告诉它现在需要处理什么;id含有通常是跟随action而定的,比如刚才的例子,id表示要处理哪篇文章。

 

我们规划搜索引擎的URL吧:

路径

页面内容

/

首页

/keyword

搜索结果页

 

于是我们可以将上面的路由代码改为:

 

public class RouteConfig

{

    public static void RegisterRoutes(RouteCollection routes)

    {

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

        routes.MapRoute(

            name: "HomePage",

            url: "",

            defaults: new { controller = "Home", action = "Index" }

        );

 

        routes.MapRoute(

            name: "SearchResult",

            url: "{keyword}",

            defaults: new { controller = "Home", action = "Search", keyword = UrlParameter.Optional }

        );

    }

}

 

注意,我们使用了一个名为Homecontroler,以及名为IndexSearch的两个actionSearch这个action带参数keyword

 

建立相应的代码和页面

建立controller

右键单击Controllers目录,选择Add=>Controller

image

 

输入名字HomeController,选择模版类型为Empty MVC controller

image

 

注意,必须使用这个名字!因为我们之前在URL路由中设置的Controller名字是Home

 

建好后得到一个比较简单的代码,将其改造成如下的样子:

 

public class HomeController : Controller

{

    //

    // GET: /

 

    public ActionResult Index()

    {

        return View();

    }

 

    //

    // GET: /keyword

 

    public ActionResult Search(string keyword)

    {

        return View();

    }

}

 

建立View

右键单击View目录,新建子目录Home(一定要与controller同名),然后右键单击Home目录,选择Add=>View

image

 

名字改为Index,其余默认:

image

 

注意,必须为Index,与action保持同名。然后用同样方法建立一个Search页面。

 

到现在为止,我们的网站可以跑了!访问根目录:

image

 

访问搜索结果页面:

image

 

建立搜索结果

建立model

考虑到搜索结果中,controller处理后需要把结果传递给页面,我们建立一个model类来表示这个数据结构。右键单击Models目录,新建一个C#代码文件,定义如下类型:

 

namespace SearchEngine.Models

{

    public class SearchResultItem

    {

        public string Title { get; set; }

        public string Link { get; set; }

        public string Description { get; set; }

    }

 

    public class SearchResult

    {

        public string Keyword { get; set; }

        public List<SearchResultItem> Results { get; set; }

    }

}

 

改造controller

改写controller中的Search方法,改成:

 

public ActionResult Search(string keyword)

{

    if (keyword == null)

    {

        return RedirectToAction("Index");

    }

 

    Models.SearchResult result = new Models.SearchResult();

    result.Keyword = keyword;

    result.Results = new List<Models.SearchResultItem>();

 

    for (int i = 0; i < 10; ++i)

    {

        Models.SearchResultItem item = new Models.SearchResultItem();

        item.Link = "http://www.streamlet.org/";

        item.Title = "溪流软件工作室";

        item.Description = "快来访问溪流软件工作室!";

 

        result.Results.Add(item);

    }

 

    return View(result);

}

 

注意,我们建立了数据result,通过View(result)传递给页面。

 

改造View

改写Search.cshtml,改为:

 

@model SearchEngine.Models.SearchResult

@{

    ViewBag.Title = "Search";

}

 

<h2>Search</h2>

 

<p>搜索@Model.Keyword”的结果:</p>

 

@foreach (var item in Model.Results)

{

<p>

    <a href="@item.Link" target="_blank">@item.Title</a><br />

    @item.Description

</p>

}

 

第一行@model声明本页面的数据模型。后面@开头的都是C#语句,剩余的是HTML。大多数情况下,Razor能识别@的结束,这比<% %><? ?>书写起来都简洁一点。

 

再访问一下搜索结果页:

 

image

美化及搜索框处理

这部分利用HTML的知识和PS功底即可。我这里简单的放了一个Logo和搜索框。首页代码如下:

 

@{

    ViewBag.Title = "世界第一搜索引擎";

}

 

@Styles.Render("~/Content/Index.css")

 

@section scripts {

    <script type="text/javascript">

        var search = function ()

        {

            var keyword = $("#keyword").val();

            window.location = "/" + keyword;

        }

    </script>

}

 

<br />

<br />

<br />

<br />

<br />

<br />

<br />

 

<div id="searchBox">

    <img src="~/Images/Logo.png" /><br />

    <br />

    <input id="keyword" type="text" />

    <input id="submit" type="submit" value="搜索" onclick="javascript: search();" />

</div>

 

页面效果如下:

image

 

搜索结果页面代码如下:

 

@model SearchEngine.Models.SearchResult

@{

    ViewBag.Title = "Search";

}

 

@Styles.Render("~/Content/Search.css")

 

@section scripts {

    <script type="text/javascript">

        var search = function ()

        {

            var keyword = $("#keyword").val();

            window.location = "/" + keyword;

        }

    </script>

}

 

<div id="searchBox">

    <a href="/"><img src="~/Images/Logo.png" /></a><br />

    <input id="keyword" type="text" value="@Model.Keyword" />

    <input id="submit" type="submit" value="搜索" onclick="javascript: search();" />

</div>

 

<br />

 

@foreach (var item in Model.Results)

{

<p>

    <a href="@item.Link" target="_blank">@item.Title</a><br />

    @item.Description

</p>

}

 

 

页面效果如下:

image

 

 

无搜索数据时的处理

目前,我们在Search方法中生成的数据是假的。实际情况中要根据实际结果来。当没有数据的时候,我们要给出友好提示。

 

因此,将controllerSearch方法改为:

 

public ActionResult Search(string keyword)

{

    if (keyword == null)

    {

        return RedirectToAction("Index");

    }

 

    Models.SearchResult result = new Models.SearchResult();

    result.Keyword = keyword;

    result.Results = new List<Models.SearchResultItem>();

 

    //for (int i = 0; i < 10; ++i)

    //{

    //    Models.SearchResultItem item = new Models.SearchResultItem();

    //    item.Link = "http://www.streamlet.org/";

    //    item.Title = "溪流软件工作室";

    //    item.Description = "快来访问溪流软件工作室!";

 

    //    result.Results.Add(item);

    //}

 

    return View(result);

}

 

Search页面相应地改为:

 

@model SearchEngine.Models.SearchResult

@{

    ViewBag.Title = "Search";

}

 

@Styles.Render("~/Content/Search.css")

 

@section scripts {

    <script type="text/javascript">

        var search = function ()

        {

            var keyword = $("#keyword").val();

            window.location = "/" + keyword;

        }

    </script>

}

 

<div id="searchBox">

    <a href="/"><img src="~/Images/Logo.png" /></a><br />

    <input id="keyword" type="text" value="@Model.Keyword" />

    <input id="submit" type="submit" value="搜索" onclick="javascript: search();" />

</div>

 

<br />

 

@if (Model.Results == null || Model.Results.Count() == 0)

{

    <strong>根据相关法律法规和政策,部分搜索结果未予显示。</strong>

}

else

{

    foreach (var item in Model.Results)

    {

<p>

    <a href="@item.Link" target="_blank">@item.Title</a><br />

    @item.Description

</p>

    }

}

 

页面效果:

image

 

例子代码:http://pan.baidu.com/s/1o6r5QgaSearchEngine.rar

演示页面:http://www.streamlet.org/Search/

 

posted on 2013-01-08 01:54  溪流  阅读(17)  评论(0编辑  收藏  举报