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


防外鏈

博客園原文地址在這里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()
        {
        }
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM