防外鏈
博客園原文地址在這里http://www.cnblogs.com/shen6041/p/3442499.html
引
Xilium CefGlue是個不錯的cef擴展工程,托管地址在這里 https://bitbucket.org/xilium/xilium.cefglue/wiki/Home
當然它還有很多工作要做,這里介紹一下怎樣利用XHR實現Js調用c#方法。代碼已經在官方Demo里,只是沒有中文資料,英文資料也幾乎沒有,這里只是把它挖出來講一下,本人毫無技術含量。ps:感謝熱心的@dmitry.azaraev郵件耐心回復。
本文參考自 http://www.wuleba.com/23614.html,感謝@flydoos給我很多啟發。
另外園子里也有介紹入門教程:http://www.cnblogs.com/liulun/archive/2013/03/18/2874276.html,建議先閱讀該系列教程。
什么是XHR
XMLHttpRequest (XHR) is an API available to web browser scripting languages such as JavaScript. It is used to send HTTP or HTTPSrequests to a web server and load the server response data back into the script.[1] Development versions of all major browsers support URI schemes beyond http: and https:, in particular, blob: URLs are supported.[2]
在這里,XHR可以向CefGlue瀏覽器發送請求,並接收回復,簡單的字符串即可通過Post傳遞,如果是復雜對象,可以使用Json轉換后傳遞。
CefGlue提供的API
RegisterSchemeHandlerFactory(string schemeName, string domainName, CefSchemeHandlerFactory factory)
該方法位於CefRuntime,在啟動Initialize后使用。其向瀏覽器注冊一個Scheme處理工廠。
三個參數:
schemeName:scheme名;
domainName:使用域 的名稱,這一個參數比較重要,在js中我們需要向這個地址發送Post請求,可以隨便填,比如 "testdomain",那么在js中請求的地址是 "http://testdomain/";
factory:處理工廠,需要來裝配一個處理handle。
C#端需要做的兩項工作
1.新建一個類DumpRequestResourceHandler,繼承自CefResourceHandler,有六個函數需要我們繼承,這里只用到前面三個。

protected override bool ProcessRequest(CefRequest request, CefCallback callback) { // return true; } protected override void GetResponseHeaders(CefResponse response, out long responseLength, out string redirectUrl) { // responseLength = -1; redirectUrl = null; } protected override bool ReadResponse(Stream response, int bytesToRead, out int bytesRead, CefCallback callback) { // bytesRead = 0; return false; } protected override bool CanGetCookie(CefCookie cookie) { return false; } protected override bool CanSetCookie(CefCookie cookie) { return false; } protected override void Cancel() { }
2.新建一個類DemoAppSchemeHandlerFactory,繼承自CefSchemeHandlerFactory
這個就是我們需要在注冊時用到的工廠,繼承他的Creat函數,返回我們上面建的DumpRequestResourceHandler實例即可。

protected override CefResourceHandler Create(CefBrowser browser, CefFrame frame, string schemeName, CefRequest request) { return new DumpRequestResourceHandler(); }
Js端需要做的工作
js端需要做的就是創建一個XmlHttpRequest,向之前注冊的地址發請求即可,代碼在園子里很多,隨便搜搜就能找到。

<script type="text/javascript"> function CreateXmlHttpRequest() { var xmlHttp = null; if (window.XMLHttpRequest) { // For Mozilla, Safari, ... xmlHttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { // For Internet Explorer xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } return xmlHttp; } function testPost() { var xmlHttp = CreateXmlHttpRequest(); var para = "id=testid&name=testname"; xmlHttp.open("POST", "http://testdomain/", false); xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xmlHttp.send(para); var result = xmlHttp.status; if (xmlHttp.readyState == 4) { if (result == 200) { var response = xmlHttp.responseText; alert(response); } } } </script>
這里的js只是舉個栗子,你也可以用異步的請求之類的,不要在意這些細節。
如何接收Post數據
回到DumpRequestResourceHandler 的ProcessRequest方法,post過來的數據就在request.PostData里,GetElements()以后把字節數組轉成字符串即可。
怎么返回數據給Js
在DumpRequestResourceHandler的GetResponseHeaders方法里,你需要回復一個接收成功的狀態:

response.MimeType = "text/html"; response.Status = 200; response.StatusText = "OK, hello from handler!";
並寫一些頭信息:

var headers = new NameValueCollection(StringComparer.InvariantCultureIgnoreCase); headers.Add("Cache-Control", "private"); headers.Add("Access-Control-Allow-Origin","*"); response.SetHeaderMap(headers);
注意這一句代碼:headers.Add("Access-Control-Allow-Origin","*"); 因為跨域的問題,如果你的html在本地,XHR的返回永遠都是0並沒有數據。這里是允許所有的跨域訪問,存在安全問題暫時不表。
你可以在這里找到更多資料:
http://blog.csdn.net/hfahe/article/details/7730944
在ReadResponse方法里把數據寫回去:
response.Write(responseData, pos, bytesToRead);
是不是跑題了?一直都沒講怎么調用c#方法啊?你特么是在逗我嗎?
......
我是這樣做的,在js的post數據里帶參數,比如我要調用的c#方法是A類中的test(string msg);
我的post參數這樣傳:
var para = "method=test&msg=testtext";
ProcessRequest拿到參數以后就知道了函數的名字和參數,將A類中的test方法反射出來執行,如需要返回值,參考上面的方法即可。
這樣做存在一些問題,比如函數無法重載、js和c#類型轉換之類的。
我這邊項目用到的基本公開給js的函數都很明確,沒有重載;另外有復雜對象,也能用json來解決。暫時繞開了這些問題,當然也不是很難解決。
官方的代碼實例可以在這里找到:
Xilium.CefGlue.Demo.DemoApp 78行,注冊scheme
Xilium.CefGlue.Demo的SchemeHandler文件夾下的DemoAppSchemeHandlerFactory、DumpRequestResourceHandler兩個類。
如果有不明白的地方,可以慢慢看代碼。
感興趣的,可以加入:WebKit/Blink 內核瀏覽器開發 QQ交流群:244840771