【茶包射手日記】WCF RIA Service的NotFound錯誤
1 |
WCF RIA Service是一種簡化RIA資料庫存取的解決方案,基本上它以Entity Framework、WCF為基礎,透過服務元件、IDE精靈、程式碼自動產生器,讓Silverlight開發人員花最少的力氣搞定資料庫的查詢新增修改刪除工作。
(想多了解一點的人可以參考MSDN Library和Silverlight網站的錄影教學,另外,LOLOTA也有一篇簡單扼要的介紹文。)
今天第一次嘗試將WCF RIA Service應用在小型專案上,一度射門中柱彈出,所幸稍後頭鎚補進。
我寫的RIA Service是用來讓Silverlight查詢Oracle資料庫,EF部分利用devart提供的Devart Entity Model(說實在話,我還是偏好較輕巧的LINQ to ORACLE,過去也發過好人卡給EF。但EF畢竟是微軟力捧的掌上明珠,比起來LINQ to SQL只是灰姑娘,RIA Service只支援EF也算印證了這點),其餘部分倒如教學文件一樣簡單順利,Visual Studio 2010 IDE做掉了大部分的苦工,三兩下程式就寫好了。
正當我感覺自已即將跟灰姑娘她姐共享榮華富貴,自此過著幸福快樂日子時,RIA Service菜鳥王子忽然被一盆涼水潑醒。
當Silverlight端透過Proxy Class,向Domain Service Class查詢資料表內容時,出現以下錯誤:
An unhandled exception ('Unhandled Error in Silverlight Application
Code: 4004
Category: ManagedRuntimeError
Message: System.ServiceModel.DomainServices.Client.DomainOperationException: Load operation failed for query 'GetEntities'. The remote server returned an error: NotFound. ---> System.ServiceModel.CommunicationException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound.
at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4(Object sendState)
at System.Net.Browser.AsyncHelper.<>c__DisplayClass2.<BeginOnUI>b__0(Object sendState)
--- End of inner exception stack trace ---
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
--- End of inner exception stack trace ---
at System.ServiceModel.DomainServices.Client.WebDomainClient`1.EndQueryCore(IAsyncResult asyncResult)
at System.ServiceModel.DomainServices.Client.DomainClient.EndQuery(IAsyncResult asyncResult)
at System.ServiceModel.DomainServices.Client.DomainContext.CompleteLoad(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.ServiceModel.DomainServices.Client.OperationBase.Complete(Exception error)
at System.ServiceModel.DomainServices.Client.LoadOperation.Complete(Exception error)
at System.ServiceModel.DomainServices.Client.DomainContext.CompleteLoad(IAsyncResult asyncResult)
at System.ServiceModel.DomainServices.Client.DomainContext.<>c__DisplayClass1b.<Load>b__17(Object )
') occurred in iexplore.exe [8472].
NotFound? 網頁查不到?? 爬了文,發現原來NotFound只是"存取WCF時發生一般性錯誤"的一級模糊訊息,此時得使用Fiddler等網路封包監看工具才能找出問題根源。
使用HttpWatch Pro查看,菜鳥王子對RIA Service又多了一點了解。原來Silverlight會透過/ClientBin/DomainClassName.svc/binary/GetEntities的URL呼叫Domain Service Class,而我所得到的NotFound錯誤應是Response完全沒有傳回任何內容所致。
做了Line-By-Line Debug,確定Domain Service Class裡的GetEntities()有正確完成查詢並取得ORACLE資料,顯然問題是出在傳回前端時,但由於WCF的部分被Domain Service Hosting所掌控,無從Debug,只好透過調整程式碼觀察結果變化。做了一些測試,加上噗友補充,發現程式的問題出在傳回資料量太大,超出WCF限制。Domain Service Class自動建立的GetEntities程式碼預設會傳回整個資料表,當不是用AdventureWorks範例資料庫而是實務資料時,傳回資料量就可能大到突破WCF RIA Service的基底限制。
只是很不幸地,WCF只是無聲無息地自盡,沒提供任何線索,才讓我迷途這麼久。但藉著這個案例,我多學會一些WCF偵錯上的小技巧,留待下回分解。
Comments
# by programlin
這問題目前RIA Service Toolkit已有機制處理了 參考 http://www.dotblogs.com.tw/programlin/archive/2010/11/11/19361.aspx