真正走进ASPNET MVC的世界才知道它的精彩
抛弃WebService在NET中用 jQuery 调用 WCF——原来抛弃WebService之后还可以用jQuery调用ASPNET MVC的Controller
Ajax为主的应用不需要ASPNET MVC原来Ajax的世界更需要ASPNET MVC
曾经天真的想法在实践中证明了它的天真但在从天真到事实的过程中得到的是成长
下面就谈谈我是如何认识到这个的相比于结论其中的过程更重要
还是以之前文章中的博客园站内短消息功能(显示当前用户短消息列表)为例开始用的是jQuery插件Templates进行列表数据绑定后来遇到了两个问题
) 在绑定时需要根据条件判断生成不同的元素比如用户发过来的短消息发件人显示为链接如果是系统通知则显示为文本Templates对这样的操作处理起来不是很方便
) 绑定后的数据无法在服务端重用有时从搜索引擎友好或者用户体验的角度在页面第一次加载时不用ajax在页面加载后点击刷新或分页链接时才使用ajax这样就要在服务端与客户端分别维护数据绑定操作
也就是说原来服务端返回的是实体类对象列表现在要返回的是将数据与Html组装起来的字符串
开始我们考虑的是一种丑陋的方法用StringBuilder进行字符串拼接生成数据绑定结果服务器端WCF服务中的代码如下
显然这种方法易出错维护性差
接着我们考虑了第二种方法(参考自Render User Control as String Template)通过Web User Control生成字符串WCF服务中的代码如下
Page page = new Page();
Control control = pageLoadControl(~/Controls/MsgListControlascx);
((IRenderable<List<SiteMsg>>)control)PopulateData(siteMsgList);
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
controlRenderControl(htw);
return sbToString();
}
}
由于MsgListControlascx的类型是动态编译生成的所以无法通过强制类型转换将control转换为MsgListControl类型然后传递数据给它
这里需要通过一个另外的IRenderable<T>接口来实现数据的绑定MsgListControl实现了这个接口代码如下
public partial class MsgListControl : UserControl IRenderable<List<SiteMsg>>
{
public void PopulateData(List<SiteMsg> siteMsgList)
{
rptMsgListDataSource = siteMsgList;
rptMsgListDataBind();
}
}
public interface IRenderable<T>
{
void PopulateData(T data);
}
在WCF服务中通过调用接口中的PopulateData方法进行数据的绑定
这个方法增加了额外的接口显得有些复杂
后来我们想到了ASPNET MVC虽然不熟悉但要尝试一下看能否更好地解决这个问题
于是上ASPNET MVC 用Razor咱们也MVC一把
应用场景在现有的VS Web Site项目中应用ASPNET MVC MsgController收到请求后由Inbox(一个Action)将包含短消息列表的整个页面视图返回给客户端当用户点击页面的刷新或者分页链接时通过Ajax发起POST请求以获取短消息列表MsgController收到请求后由List(一个Action)将短消息列表的视图返回给客户端
期望的效果短消息列表视图能重用Inbox与List使用的是同一个视图
一开始遇到了两个小问题
a) MapRoute配置之后访问出现HTTP Error Not Found错误原因是访问的网址没有文件名未走ASPNET管线解决方法是在nfig的systemwebServer中加上以下的配置
<validation validateIntegratedModeConfiguration=false />
<modules runAllManagedModulesForAllRequests=true />
b) 继续访问出现The resource cannot be found错误解决方法由于用的是Web Site项目要将Controllers文件夹移至App_Code
然后进入MVC相关代码编写先从Ajax调用部分开始
Controller的代码如下
public class MsgController : Controller
{
[HttpPost]
public ActionResult List(SiteMsgQuery msgQuery)
{
List<SiteMsg> siteMsgList = GetInboxMsgList(msgQuery);
return View(MsgList siteMsgList);
}
}
需要注意的就一个地方[HttpPost]既然是Ajax调用当然要响应POST请求
View的代码(MsgListcshtml)如下
@using CNBlogsUcHomeExternalServiceMsgWcfService
@model List<SiteMsg>
@foreach(SiteMsg msg in Model){
<div class=msg_item>
<div class=msg_sender>@msgSenderName</div>
<div class=msg_title><a /msg/item/@msgid/>@msgSubject</a></div>
<div class=msg_sendtime>@msgSendTimeToString(yyyyMMdd HH:mm)</div>
</div>
}
比在ascx中写起来方便多了
客户端js调用代码如下
function GetMsgList(pageIndex pageSize) {
var msgQuery = {}
msgQueryPageIndex = pageIndex;
msgQueryPageSize = pageSize;
$ajaxSettingsdataType = plain/text;//不要用json
$ajaxSettingsurl = /msg/list;
$ajaxSettingsdata = {msgQuery: + JSONstringify(msgQuery) + };
$ajaxSettingssuccess = function (data) {
$(#msg_listl(data);
};
$ajax();
}
需要注意的是两个地方(因为服务器端Controller返回的不是json格式的数据)
a) dataType不要用json用jQuery默认的就行如果指定的话就用plain/text
b) 返回数据就在data中不要通过datad获取
这样用ASPNET MVC就轻松搞定Ajax调用比之前的WCF StringBuider ascx都要方便
原来在ASPNET MVC中使用Ajax如此方便完全可以取代以前用的WCF中转站
解决了Ajax的问题接着处理整个页面的显示
在页面的View中直接重用刚才Ajax所用的View就行了示例代码如下
View(Inboxcshtml)
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
@HtmlPartial(MsgList)
</body>
</html>
Control
public class MsgController : Controller
{
public ActionResult Inbox()
{
SiteMsgQuery msgQuery = new SiteMsgQuery()
{
PageIndex =
PageSize =
};
List<SiteMsg> siteMsgList = GetInboxMsgList(msgQuery);
return View(Inbox siteMsgList);
}
}
搞定!真的很方便!想要的解决方案就是它ASPNET MVC!