RIA domainservice/context call fails from Silverlight sometimes - silverlight

I have a very strange problem: I'm developing a Silverlight business application with RIA services.
I have some DomainServices on the server-side, and with one of them I'm having the problem, that sometimes calling one of the methods fails (on the SL client, I get "NotFound" exception, and the request doesn't event arrive to the server (I put a breakpoint into the constructor of the domainservice)!
What makes things strange even more:
If the call fails from the SL client, then I start Fiddler2, then the second (or any consecutive) call is working properly! If I close fiddler, it becomes unstable again.
If I rename the method which I would like to call (via refactor), call renamed method on the context at SL client side too, then everytime I make the call it is successful!
Here is my suspicios method:
[Invoke]
public void RegisterTrainingProgramCompletion(bool isCompleted, int result, string sportsManNote)
{
//...
}
If I rename this method to "RegisterTpCompletion", then it works (unbelievable)!
The DomainService is marked with some attributes:
[EnableClientAccess()]
[RequiresAuthentication()]
public class NextTrainingProgramDomainService : DomainService
I managed to somehow log the server-side, and got the following exception from the WCF stack:
There is a problem with the XML that was received from the network. See inner exception for more details. at System.ServiceModel.Channels.HttpInput.DecodeBufferedMessage(ArraySegment`1 buffer, Stream inputStream)
at System.ServiceModel.Channels.HttpInput.ReadBufferedMessage(Stream inputStream)
at System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception& requestException)
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
at System.ServiceModel.AspNetPartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
So for some unknown reason the clint (SL-app) does not flush properly the request? I'm starting to worry :(((
My callers (SL client) are authenticated with custom forms authentication.
I know you could say, leave it then as it is, but this drives me crazy, I want to know what's the problem, so I do not run into it again.
Thanks!
Bye,
Csabi

I suspect it is URL issue, mostly URL can only be few kbs long. Now I don't know the size but in RIA services, it uses URL to send your filter as querystring.
And names of your method are also big, it is reaching max limit of URL. When it is working even with big name your filter part may be empty but if you add more filters you will face errors.

Related

Pass byte array from WPF to WebApi

tl;dr What is the best way to pass binary data (up to 1MBish) from a WPF application to a WebAPI service method?
I'm currently trying to pass binary data from a WPF application to a WebAPI web service, with variable results. Small files (< 100k) generally work fine, but any larger and the odds of success reduce.
A standard OpenFileDialog, and then File.ReadAllBytes pass the byte[] parameter into the client method in WPF. This always succeeds, and I then post the data to WebAPI via a PostAsync call and a ByteArrayContent parameter.
Is this the correct way to do this? I started off with a PostJSONAsync call, and passed the byte[] into that, but thought the ByteArrayContent seemed more appropriate, but neither work reliably.
Client Method in WPF
public static async Task<bool> UploadFirmwareMCU(int productTestId, byte[] mcuFirmware)
{
string url = string.Format("productTest/{0}/mcuFirmware", productTestId);
ByteArrayContent bytesContent = new ByteArrayContent(mcuFirmware);
HttpResponseMessage response = await GetClient().PostAsync(url, bytesContent);
....
}
WebAPI Method
[HttpPost]
[Route("api/productTest/{productTestId}/mcuFirmware")]
public async Task<bool> UploadMcuFirmware(int productTestId)
{
bool result = false;
try
{
Byte[] mcuFirmwareBytes = await Request.Content.ReadAsByteArrayAsync();
....
}
Web Config Settings
AFAIK these limits in web.config should be sufficient to allow 1MB files through to the service?
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
<httpRuntime targetFramework="4.5" maxRequestLength="2097152"/>
I receive errors in WebAPI when calling ReadAsByteArrayAsync(). These vary, possibly due to the app pool in IIS Express having crashed / getting into a bad state, but they include the following (None of which have lead to any promising leads via google):
Specified argument was out of the range of valid values. Parameter name: offset
at System.Web.HttpInputStream.Seek(Int64 offset, SeekOrigin origin)\r\n
at System.Web.HttpInputStream.set_Position(Int64 value)\r\n at System.Web.Http.WebHost.SeekableBufferedRequestStream.SwapToSeekableStream()\r\n at System.Web.Http.WebHost.Seek
OR
Message = "An error occurred while communicating with the remote host. The error code is 0x800703E5."
InnerException = {"Overlapped I/O operation is in progress. (Exception from HRESULT: 0x800703E5)"}
at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)\r\n
at System.Web.Hosting.IIS7WorkerRequest.ReadEntityCoreSync(Byte[] buffer, Int32 offset, Int32 size)\r\n
at System.Web.Hosting.IIS7WorkerRequ...
Initially I thought this was most likely down to IIS Express limitations (running on Windows 7 on my dev pc) but we've had the same issues on a staging server running Server 2012.
Any advice on how I might get this working would be great, or even just a basic example of uploading files to WebAPI from WPF would be great, as most of the code I've found out there relates to uploading files from multipart forms web pages.
Many thanks in advance for any help.
tl;dr It was a separate part of our code in the WebApi service that was causing it to go wrong, duh!
Ah, well, this is embarrassing.
It turns out our problem was down to a Request Logger class we'd registered in WebApiConfig.Register(HttpConfiguration config), and that I'd forgotten about.
It was reading the request content via async as StringContent, and then attempting to log it to the database in an ncarchar(max) field. This itself is probably OK, but I'm guessing all the weird problems started occurring when the LoggingHandler as well as the main WebApi controller, were both trying to access the Request content via async?
Removing the LoggingHandler fixed the problem immediately, and we're now able to upload files of up to 100MB without any problems. To fix it more permanently, I guess I rewrite of the LoggingHandler is required to set a limit on the maximum content size it tries to log / to ignore certain content types.
It's doubtful, but I hope this may be of use for someone one day!
public class LoggingHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
LogRequest(request);
return base.SendAsync(request, cancellationToken).ContinueWith(task =>
{
var response = task.Result;
// ToDo: Decide if/when we need to log responses
// LogResponse(response);
return response;
}, cancellationToken);
}
private void LogRequest(HttpRequestMessage request)
{
(request.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x =>
{
try
{
var callerId = CallerId(request);
var callerName = CallerName(request);
// Log request
LogEntry logEntry = new LogEntry
{
TimeStamp = DateTime.Now,
HttpVerb = request.Method.ToString(),
Uri = request.RequestUri.ToString(),
CorrelationId = request.GetCorrelationId(),
CallerId = callerId,
CallerName = callerName,
Controller = ControllerName(request),
Header = request.Headers.ToString(),
Body = x.Result
};
...........

OutOfMemoryException while bulk data processing with WCF RIA & WF4

I have an existing Silverlight 5 application. I'm adding a page to it to allow users to process mass updates to data in a 3rd party database system. The application currently uses WCF RIA services to communicate to the 3rd party system via SOAP. The functionality of the update is contained in a Workflow 4 application I created and is referenced as an assembly on the server-side of the SL application. Lastly, the application is hosted right now in my local instance of IIS 7.5 running on Windows 7; I'm also debugging with IIS, not the VS dev server.
At the basic level, the application functions as follows:
Select text file
Click "Start" button
Event handler creates an instance of a user-defined Type that keeps track of the batch
Event handler creates a new BackgroundWorker instance and wires up handlers for the DoWork, ProgressChanged, and RunWorkerCompleted events
Event handler calls RunWorkerAsync()
Here's the shortened code for the DoWork event handler, since that's where the majority of the work is done.
private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
{
var worker = sender as BackgroundWorker;
// Iterate through each record of data file and call the 'UpdateAddress' function
// of the AddressDomainService which, in turn, executes the Workflow
foreach (var item in batchProcess.FileData)
{
// Check if operation has been cancelled
if (worker.CancellationPending)
{
doWorkEventArgs.Cancel = true;
break;
}
. . .
// Invoke THINKComm.CustomerAddressUpdate Workflow via AddressContext
var invokeOp = _addressDomainContext.UpdateAddress(activityData);
// 'activityData' is an instance of Dictionary<string, string>
invokeOp.Completed += (o, args) => InvokeOpOnCompleted(o, args, batchProcess);
}
}
The handlers for the ProgressChanged and RunWorkerCompleted events, as well as the Completed event of the InvokeOperation instance all, for the most part, update a part of the UI. If you think posting any of that code would be helpful, I'd be happy to update the post.
Speaking of UI, the parts that are updated by the event handlers are two ProgressBar controls - one that tracks the records as they're read from the file and a second one that tracks the records as the update has taken place on the 3rd party database.
Getting to the actual problem...
I've processed files of 10, 100, and 1,000 records with no problem. I then attempted to process a complete file containing ~15,000 records (or 1,907KB of data). The process starts and I can see in the debugger output that the Workflow is being executed. About a quarter of the way through or so, I get an OutOfMemoryException. Here's the stack trace:
at System.ServiceModel.DomainServices.Client.WebDomainClient`1.BeginInvokeCore(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainClient.BeginInvoke(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainContext.InvokeOperation(String operationName, Type returnType, IDictionary`2 parameters, Boolean hasSideEffects, Action`1 callback, Object userState)
at THINKImportSystem.Web.Address.AddressDomainContext.UpdateAddress(Dictionary`2 activityData)
at THINKImportSystem.BatchProcessPage.BwOnDoWork(Object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
at THINKImportSystem.BatchProcessPage.<>c__DisplayClass10.<StartButtonClick>b__6(Object s, DoWorkEventArgs args)
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.OnRun(Object argument)
Then, the JIT debugger pops up with an error of Unhandled Error in Silverlight Application Code:4004 with a message of System.ServiceModel.DomainServices.Client.DomainOperationException: Invoke operation 'UpdateAddress' failed. Error HRESULT E_FAIL has been returned from a call to a COM component.
I should mention that, sometimes, I get the JIT debugger first. I see in the Debug output that threads are still exiting, and then about 10 or 20 seconds later, the VS debugger pops up with the out of memory exception.
My best guess is that, objects somewhere (maybe related to the DomainService?) aren't being released and therefore, memory usage is building. From what I understand, IIS places restrictions on the amount of memory an application can use, but I can't tell if that's the case here or not.
I was thinking that, each time a record in the file is processed, the objects related to it's processing would be released and therefore overall memory usage would be pretty low. But obviously I'm not understanding how everything is being executed!
I was also wondering if using the TPL as opposed to BackgroundWorker would make a difference?

Random System.NotSupportedException on WP7

Sporadically, I receive an error in my WP7 Silverlight application. The error is a random "System.NotSupportedException". This error is thrown occassionally when the following code is executed:
// 1. Build the url
string serviceURL = "http://www.mydomain.com/service.svc/param1/param2";
// 2. Asynchronously execute the query using HttpWebRequest instead of WebClient. There is a UI performance issue with the WebClient currently
WebRequest request = HttpWebRequest.Create(serviceUrl);
request.BeginGetResponse(new AsyncCallback(MyService_Completed), request);
...
private void MyService_Completed(IAsyncResult result)
{
// Do stuff
}
I have verified that the URL I am sending is correct. Please note, that this request is part of my view model, which may have other network requests fired off at the same time. I have no idea why this happens ocassionally. Can anybody point out any potential reasons?
Thank you!
When this happens, make sure you look at the View Detail part of the exception report. It might be that your service is refusing connection or the data passed is invalid. NotSupported is a very general exception that covers many possible situations.
A similar question has been asked previously. If you look at the comments the original poster added to the answer, he claims to have solved the problem by replacing
request.BeginGetResponse(new AsyncCallback(MyService_Completed), request);
with
request.BeginGetResponse( MyService_Completed, request);

How to register own protocol using the WebBrowser control?

In a WP7 Silverlight application with a WebBrowser control I want to use an own protocol like "myttp://" to deliver some local content. I can't use Navigate() to an IsolatedStrorage because some content will by created on demand. For the same reason NavigateToString() is also not usable for me.
I tried to register a WebRequestCreator descend for my MYTP protocol
myCreator = new MyRequestCreator();
WebRequest.RegisterPrefix("mytp://", myCreator);
but it isn't called from the browser control if I navigate to "mytp://test.html".
If I create a WebRequest via code
WebRequest request;
request = WebRequest.Create("mytp://test.html");`
everythings works fine.
Any suggestions what is wrong or how to do it?
The WebBrowser control will use the Windows Phone Internet Explorer Browser's HTTP stack to statisfy web requests. This HTTP stack is entirely separate from the Client HTTP stack being used by the application. Hence the browser does not see your protocol at all.
I agree with AnthonyWJones words, though I dont know, what exactly he meant by "Browser HTTP stack".
The standard Silverlight's "access to Browser's stack" (used to handle sessions etc) in form of System.Net.Browser.WebRequestCreator.BrowserHttp httprequest factory (versus the "normal/aside" System.Net.Browser.WebRequestCreator.ClientHttp factory) is actually available to the application code in WP7. It is hidden from the SDK, but available on the device and with small effort, the application can use it, for example, to have its emitted cookies in sync with the Browser's cache. For description, please see my humble other post
However, while using that factory and having all your session/cookies/userauth handling within those connections in sync with the WebBrowser, despite being very similar to the ClientHttp factory, you find (at least in 7.0 and 7.1 versions) that it is completely ignorant of any custom prefixes. Trying to open anything with this factory results in (WP7 v. Mango 7.1):
A first chance exception of type 'System.Net.ProtocolViolationException' occurred in System.Windows.dll
at System.Net.Browser.BrowserHttpWebRequest.InternalBeginGetRequestStream(AsyncCallback callback, Object state)
at System.Net.Browser.AsyncHelper.BeginOnUI(BeginMethod beginMethod, AsyncCallback callback, Object state)
at System.Net.Browser.BrowserHttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
at MyApp.MyPage..ctor()
relevant code snippet of the MyPage:
public class WRC : IWebRequestCreate { public WebRequest Create(Uri uri) { return null;/*BREAKPOINT1*/ } }
WebRequest.RegisterPrefix("js://", new WRC()); // register the above handler
brwHttp = (IWebRequestCreate)typeof(System.Net.Browser.WebRequestCreator).GetProperty("BrowserHttp").GetValue(null, null);
var tmp = brwHttp.Create(new Uri("js://blah.blah.blah"));
var yyy = tmp.BeginGetResponse(callback, "wtf");
var response = tmp.EndGetResponse(yyy); /*BREAKPOINT2*/
var zzz = tmp.BeginGetRequestStream(callback, "wtf"); /*<---EXCEPTION*/
var stream = tmp.EndGetRequestStream(zzz); /*BREAKPOINT3*/
Execution results:
breakpoint1 never hit
breakpoint2 allows to see that "response" is NULL
breakpoint3 never hit due to the exception pasted above
My conclusion is, that the Silverlight Browser's stack is hardcoded to use some builtin set of prefixes, and all other prefixes are ignored/throw ProtocolViolation. My guess is, that in WP7 (7.0, 7.1) they are actually hardcoded to use http since my custom "js://" was passed to a BrowserHttpWebRequest.InternalBeginGetRequestStream as it's visible on the stacktrace :)
That confirms what Anthony had written - no way of having custom protocol handlers to work gracefully with the Silverlight's Browser Stack API.
However, I cannot agree with that the WebBrowser uses this connection factory. While is it true that the hidden factory is called BrowserHttp, and is true that it shares some per-user or per-session settings with the webbrowser, everything I try tens to indicate that the WebBrowser component uses yet completly other factory for its connections, and quite probably it is some native one. As an argument for that, I can only provide that I was able to successfully replace the original BrowserHttp factory with my simple custom implementation of it (both on the emulator and the phone), and with at least 6 webbrowsers in my current app, it wasn't used at all, not even once! (neither on the emulator, nor phone)

Windows Phone 7 App Quits when I attempt to deserialize JSON

I'm developing my first windows phone 7 app, and I've hit a snag. basically it's just reading a json string of events and binding that to a list (using the list app starting point)
public void Load()
{
// form the URI
UriBuilder uri = new UriBuilder("http://mysite.com/events.json");
WebClient proxy = new WebClient();
proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(OnReadCompleted);
proxy.OpenReadAsync(uri.Uri);
}
void OnReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
var serializer = new DataContractJsonSerializer(typeof(EventList));
var events = (EventList)serializer.ReadObject(e.Result);
foreach (var ev in events)
{
Items.Add(ev);
}
}
}
public ObservableCollection<EventDetails> Items { get; private set; }
EventDetails is my class that wraps the json string. this class has to be correct because it is an exact copy of the class used by that website internally from which the json is generated...
I get the json string correctly from the webclient call (I read the memorystream and the json is indeed there) but as soon as I attempt to deserialize the string, the application exits and the debugger stops.
I get no error message or any indication that anything happen, it just stops. This happens if I type the deserialize method into the watch window as well...
I have already tried using JSON.net in fact I thought maybe it was a problem with JSON.net so I converted it to use the native deserializer in the .net framework but the error is the same either way.
why would the application just quit? shouldn't it give me SOME kind of error message?
what could I be doing wrong?
many thanks!
Firstly, the fact that you have some string there that looks like JSON does not mean that you have a valid JSON. Try converting a simple one.
If your JSON is valid, it might be that your JSON implementation does not know how to convert a list to EventList. Give it a try with ArrayList instead and let me know.
The application closes because an unhandled exception happens. If check the App.xaml.cs file you will find the code that closes your app. What you need to do is try catch your deserialization process and handle it locally. So most likely you have some JSON the DataContractJsonSerializer does not like. I have been having issue with it deserializing WCF JSON and have had to go other routes.
You may want to check to ensure your JSON is valid, just because your website likes it does not mean it is actually valid, the code on your site may be helping to correct the issue. Drop a copy of your JSON object (the string) in http://jsonlint.com/ to see if it is valid or not. Crokford (the guy who created JSON) wrote this site to validate JSON, so I would rely on it more than your site ;) This little site has really helped me out of some issues over the past year.
I ran into this same kind of problem when trying to migrate some existing WM code to run on WP7. I believe that the WP7 app crashes whenever it loads an assembly (or class?) that references something that's not available in WP7. In my case, I think it was Assembly.Load or something in the System.IO namespace, related to file access via paths.
While your case might be something completely different, the symptoms were exactly the same.
The only thing I can recommend is to go through the JSON library and see if it's referencing base classes that are not allowed in WP7. Note that it doesn't even have to hit the line of code that's causing the issue - it'll crash as soon as it tries to hit the class that contains the bad reference.
If you can step into the JSON library, you can get a better idea of which class is causing the problem, because as soon as the code references it, the whole app will crash and the debugger will stop.

Resources