2

I'm running into a very strange behavior in C#/.NET 3.5...

I am writing a class which hooks into upload pipeline of a content management system. The CMS executes this hook via reflection.

For some unknown reason the following code fails by throws a NullRef ("Files" is an HttpFileCollection).

foreach (var fileKey in args.Files.AllKeys)
{
     // Do Stuff
}

After adding a NullRef check before the statement makes the loop succeed. The uploaded files are identical in both cases. The return statement never gets executed, since the null condition fails.

if (args.Files == null ) return;
foreach (var fileKey in args.Files.AllKeys)
{
   // Do Stuff
}

I am totally stumped by this. Any ideas?

Full Stack Trace

    ** Exception: System.Web.HttpUnhandledException **
    Message: Exception of type 'System.Web.HttpUnhandledException' was thrown.
    Source: System.Web
    at System.Web.UI.Page.HandleError(Exception e)
    at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
    at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
    at System.Web.UI.Page.ProcessRequest()
    at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
    at System.Web.UI.Page.ProcessRequest(HttpContext context)
    at ASP.sitecore_shell_applications_flashupload_advanced_uploadtarget_aspx.ProcessRequest(HttpContext context)
    at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
    at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

    ** Nested Exception ** 
    Exception: System.Reflection.TargetInvocationException
    Message: Exception has been thrown by the target of an invocation.
    Source: mscorlib
    at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes,        RuntimeTypeHandle typeOwner)
    at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes,        RuntimeTypeHandle typeOwner)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
    at Sitecore.Reflection.ReflectionUtil.InvokeMethod(MethodInfo method, Object[] parameters, Object obj)
    at Sitecore.Pipelines.Processor.Invoke(PipelineArgs args)
    at Sitecore.Nexus.Pipelines.NexusPipelineApi.Resume(PipelineArgs args, Pipeline pipeline)
    at Sitecore.Pipelines.Pipeline.Resume()
    at Sitecore.Pipelines.Pipeline.DoStart(PipelineArgs args)
    at Sitecore.Pipelines.Pipeline.Start(PipelineArgs args, Boolean atomic)
    at Sitecore.Pipelines.Pipeline.Start(PipelineArgs args)
    at Sitecore.Shell.Applications.FlashUpload.Advanced.UploadTarget.HandleUpload()
    at Sitecore.Shell.Applications.FlashUpload.Advanced.UploadTarget.OnLoad(EventArgs e)
    at System.Web.UI.Control.LoadRecursive()
    at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

    ** Nested Exception **
    Exception: System.NullReferenceException
    Message: Object reference not set to an instance of an object.
    Source: Sitecore.CustomExtensions
    at Sitecore.CustomExtensions.StreamingMediaUploader.Process(UploadArgs args) in C:\...\Sitecore.CustomExtensions\StreamingMediaUploader.cs:line 33
Greg R
  • 1,670
  • 4
  • 26
  • 46
  • Can you provide the full stack trace of the exception? – qbeuek Sep 15 '10 at 17:58
  • Your NullRef check before the statement hardly makes the loop succeed, right? It makes you return from the method... – Kirk Woll Sep 15 '10 at 18:02
  • So after the check, it is always not NULL and it never returns, i.e. this extra check makes it always having value? – Aliostad Sep 15 '10 at 18:07
  • @Kirk - no, it DOES NOT EXIT, it actually goes into the loop. Which is why this is so crazy. So it checks the condition, args.Files is not null, and it goes into the loop. Otherwise it throws a null ref. on args.Files. – Greg R Sep 15 '10 at 18:09
  • Then I agree with qbeuek and suspect the exception originates further inside. How is args.Files defined? And please do post the entire stack trace. – Kirk Woll Sep 15 '10 at 18:20
  • args.Files is HttpFileCollection as per above – Greg R Sep 15 '10 at 18:22
  • @Aliostead - Yes, it does have a value and the extra check makes the value "appear" – Greg R Sep 15 '10 at 18:29

1 Answers1

0

Just a guess, but there is probably some unexpected behavior (possibly a bug) in the CMS. Bug or not, your contract with the CMS is not fully defined.

The reason the uploaded files match is because your method was likely called multiple times with the final call raising the exception.

Given you're working with an app you don't control, your solution is correct -- you must check everything you're given before you use it.

Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
  • I'm skeptical of this, since args is just a wrapper around HttpFileCollection, which is a generic .NET construct. I'm not fully convinced by the exception that this is due to CMS – Greg R Sep 15 '10 at 18:31
  • @Greg R: You should put some logging in for every time your method is called. I would bet it's more than once (with the last one requiring the null check). – Austin Salonen Sep 15 '10 at 19:32
  • I have a breakpoint set and I'm attaching a debugger, it is being called only once – Greg R Sep 15 '10 at 21:23