Xilium.CefGlue利用XHR實現Js調用c#方法

防外鏈javascript

博客園原文地址在這裏http://www.cnblogs.com/shen6041/p/3442499.htmlhtml

java

Xilium CefGlue是個不錯的cef擴展工程,託管地址在這裏 https://bitbucket.org/xilium/xilium.cefglue/wiki/Homeweb

固然它還有不少工做要作,這裏介紹一下怎樣利用XHR實現Js調用c#方法。代碼已經在官方Demo裏,只是沒有中文資料,英文資料也幾乎沒有,這裏只是把它挖出來說一下,本人毫無技術含量。ps:感謝熱心的@dmitry.azaraev郵件耐心回覆。chrome

本文參考自 http://www.wuleba.com/23614.html,感謝@flydoos給我不少啓發。json

另外園子裏也有介紹入門教程:http://www.cnblogs.com/liulun/archive/2013/03/18/2874276.html,建議先閱讀該系列教程。c#

什麼是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()
        {
        }
View Code

2.新建一個類DemoAppSchemeHandlerFactory,繼承自CefSchemeHandlerFactory
這個就是咱們須要在註冊時用到的工廠,繼承他的Creat函數,返回咱們上面建的DumpRequestResourceHandler實例便可。

        protected override CefResourceHandler Create(CefBrowser browser, CefFrame frame, string schemeName, CefRequest request)
        {
            return new DumpRequestResourceHandler();
        }
View Code

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>
View Code

這裏的js只是舉個栗子,你也能夠用異步的請求之類的,不要在乎這些細節。

如何接收Post數據

回到DumpRequestResourceHandler 的ProcessRequest方法,post過來的數據就在request.PostData裏,GetElements()之後把字節數組轉成字符串便可。

怎麼返回數據給Js

在DumpRequestResourceHandler的GetResponseHeaders方法裏,你須要回覆一個接收成功的狀態:

response.MimeType = "text/html";
            response.Status = 200;
            response.StatusText = "OK, hello from handler!";
View Code

並寫一些頭信息:

            var headers = new NameValueCollection(StringComparer.InvariantCultureIgnoreCase);
            headers.Add("Cache-Control", "private");
            headers.Add("Access-Control-Allow-Origin","*");
            response.SetHeaderMap(headers);
View Code

注意這一句代碼:headers.Add("Access-Control-Allow-Origin","*"); 由於跨域的問題,若是你的html在本地,XHR的返回永遠都是0並無數據。這裏是容許全部的跨域訪問,存在安全問題暫時不表。

你能夠在這裏找到更多資料:

http://stackoverflow.com/questions/15977151/loading-local-content-through-xhr-in-a-chrome-packaged-app

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

相關文章
相關標籤/搜索