WebDavServer
WebDavServer copied to clipboard
How to propagate exceptions after a lock is in place?
Hi,
We are facing an issue in our project, when We need to throw and exception during a PutAsync action that is called just after the LockAsync action. However, even when the exception is bubbled up and it is a type not handled by the WebDavExceptionFilter, the consumer or client of the WebDav server does not receives the exception. By the way, the UnlockAsync action is always called, regardless the exception we are throwing.
On the other hand, if the exception is throw during the PutAsync action but before the LockAsync, then the consumer receives the exception.
Can you please tell us how could we propagate the the caller or consumer an exception type thrown from an action just after the lock?
Thank you very much in advance.
Regards,
Rodrigo
Sorry, I'm not really sure what you mean. There are either exceptions handled by ASP.NET Core itself and those handled by the custom IExceptionFilter
implementation (WebDavExceptionFilter
), which handles the following exceptions:
-
NotImplementedException
resulting in a HTTP 501 response -
NotSupportedException
resulting in a HTTP 501 response -
WebDavException
resulting in either:- HTTP 304 response
- WebDAV status code +
multistatus
response
-
UnauthorizedAccessException
resulting in a WebDAV status code +multistatus
response
I suggest that you implement your own IExceptionFilter
to handle all other kinds of exceptions by returning a multistatus
response and the correct HTTP status code.
EDIT: Clarification
Hi,
It's OK.
The issue we are facing is that we are throwing an exception in the PutAsync action that is called just after the LockAsync action; but this exception is not catch by the application that interacts with the WebDav, it assumes that the action happened correctly. However, Windows shows us a dialog that looks like this:
Any idea of how could we circunvent the windows dialog and catch the exception on the consumer application of the WebDav?
Thank you.
Kind regards,
Rodrigo
What kind of exception do you get?
Hi,
That's the point. The consumer application of the WebDav is not catching any exception; it continues as if the WebDav has successfully added/copied the file it is sending, however the dialog I copied in my previous message appears due to the exception that is being thrown from the PutAsync.
We throw this exception on purpose, and We would like to have it being capture by the consumer application of the WebDav, but so far it has not been possible, and the only thing that tells us that it actually happen (beyond knowing its existence because we code it) is that dialog from the operative system.
The exception type We're throwing on purpose from the PutAsync is a System.IO.IOException
.
Thank you.
Kind regards,
Rodrigo
Aha, so it's an IOException
, that was the missing piece. Then I suggest that you implement and register your own IExceptionFilter
and return the correct HTTP status code and the corresponding multistatus
response.
We tried that, and it didn't work.
Our suspicion is that the operative system (Windows) is swallowing the exception and showing the dialog form a previous comment, and that is why the consumer application is not catching it.
But it is a suspicion, and would like another opinion, specially from the creator of the library and your experience with the WebDav protocol.
Hi,
Do you have an example on how to wrap an exception within a multistatus
(HTTP 207) response to get a message more or less like this one? -->
<?xml version="1.0"?>
<a:multistatus
xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"
xmlns:a="DAV:">
<a:response>
<a:href>http://server/public/test2/item1.txt</a:href>
<a:propstat>
<a:status>HTTP/1.1 500 Server Error</a:status>
<a:prop>
<a:getcontenttype>text/plain</a:getcontenttype>
<a:getcontentlength b:dt="int">33</a:getcontentlength>
</a:prop>
</a:propstat>
</a:response>
</a:multistatus>
Thank you.
Kind regards,
Rodrigo
Hi again,
Well, I think We found the way to create the multistatus
but it didn't work either.
This is our custom IExceptionFilter
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FubarDev.WebDavServer;
using FubarDev.WebDavServer.AspNetCore;
using FubarDev.WebDavServer.Model;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
namespace TestWebDav
{
public class TestWebDavExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
if (context.ExceptionHandled)
{
return;
}
if (context.Exception is WebDavException webDavException)
{
return;
}
context.Result = BuildResultForStatusCode(context, WebDavStatusCode.BadGateway, context.Exception.Message);
}
private static IActionResult BuildResultForStatusCode(ExceptionContext context, WebDavStatusCode statusCode, string message)
{
var result = new WebDavResult<multistatus>(
statusCode,
new multistatus()
{
response = new[]
{
new response()
{
href = context.HttpContext.Request.GetEncodedUrl(),
ItemsElementName = new[] { ItemsChoiceType2.status, },
Items = new object[] { new Status(context.HttpContext.Request.Protocol, statusCode, message).ToString() },
},
},
});
var dispatcher = context.HttpContext.RequestServices.GetService<IWebDavDispatcher>();
return new WebDavIndirectResult(dispatcher, result, null);
}
}
}
This works as expected, however Windows still shows us the same dialog.
In any case, thanks for the help.
Kind regards,
Rodrigo
The changes you made are also available in the release/2.0 branch, but I used an ExceptionFilterAttribute instead of the IExceptionFilter.
I'll leave this ticket open, because maybe we need to return the error
element too, together with an element that's a Microsoft WebDAV extension?