405 Error on HTTP Delete

I'm getting a 405 Error from my local web server when I try to use WCF Data Services to delete an object using the Entity Framework from within a WPF application.  I can see from the IIS7 log that the DELETE verb is being used.  I've checked the handler mappings for .svc files.  They're set to ALL VERBS.  I'm not sure what else I need to set/enable.  Can anyone help?  It seems like it has to be something incredibly simple that I'm missing.

I've included a sample of my routine for reference purposes.
'====================================================================================
Public Function DeleteCapacityTemplateDetail(ByVal strTemplateID As String, _
                                             ByVal strGroupID    As String) _
                                             As Boolean
'====================================================================================
' Purpose:  To delete a single capacity template detail record
' Accepts:  strTemplateID   - the ID of the template for which the capacity template
'                             details are to be deleted.
'           strGroupID      - the ID of the group for which the capacity template
'                             details are to be deleted.
' Returns:  True if successful.  Otherwise false
' Affects:  Deletes a capacity template record
' Assumes:  That the database connection is already established  
'====================================================================================

    ' Declare return value
    ' ---------------------------------------------------------------------
    Dim blnReturnValue As Boolean = False

    Try
        ' Locate the entity to be deleted using the provided keys.
        ' -----------------------------------------------------------------
        Dim entCapacityTemplate = (From CapacityTemplateDetail As tCAPSCapacityTemplateDetail _
                                   In m_dscDatabaseContext.tCAPSCapacityTemplateDetail _
                                   Where CapacityTemplateDetail.GROUP_ID = strGroupID _
                                   And   CapacityTemplateDetail.TEMPLATE_ID = strTemplateID _
                                   Select CapacityTemplateDetail).Single
            
        ' Delete the found entity
        ' -----------------------------------------------------------------
        With m_dscDatabaseContext
            ' Delete the object from the database
            .DeleteObject(entCapacityTemplate)

            ' Call SaveChanges to write the changes to the database
            .SaveChanges()
        End With

        ' If code execution reaches this point, it can be assumed that the
        ' delete was successful.  Set the return value accordingly.
        ' -----------------------------------------------------------------
        blnReturnValue = True

    Catch ex As Exception
        ' Send the exception to the standard error handler
        ' -----------------------------------------------------------------
        Dim clsErrorMessageBox As ErrorMessageBox = New ErrorMessageBox(ex, m_culCurrent)
        clsErrorMessageBox.Show(p_blnSilent:=True)

    End Try

    ' Return the collection
    ' ---------------------------------------------------------------------
    DeleteCapacityTemplateDetail = blnReturnValue

End Function

Open in new window

jmgroftAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

blandyukCommented:
Allowing your web server to use the DELETE verb is very dangerous. The only verbs you should allow is:

GET
HEAD
POST

I'd suggest changing your WCF framework to use another method of managing your data.
0
jmgroftAuthor Commented:
I appreciate the concern, but this is a learning exercise.  It's not the whole web server.  It's a single virtual directory dedicated to the web service that I'm calling - unless I have to enable it for the entire web server to get it to work.  In either case, I want to understand why it's not working now  (it appears that it should be)  and what I need to do to make it work so that I can learn from it.

Ultimately, if it's dangerous option, I can modify the web service to create a service operation that makes use of a stored procedure.  This doesn't have to be the final solution.  In the meantime, rather than just telling me it's dangerous, can you explain how to make it work?  I'll take the warning under advisement.


0
blandyukCommented:
In IIS7, have you allowed the DELETE verb in the "Request Filtering" section under "Verbs"? Details from your IIS logs would be useful at this point.
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

jmgroftAuthor Commented:
At the moment, it is not specifically enabled in Request Filtering.  I had done that yesterday (for the virtual directory where the data service is running) but it made no difference, so I turned it off again.  I've attached the section of the log where you can see the delete verb failing.


#Software: Microsoft Internet Information Services 7.5
#Version: 1.0
#Date: 2010-03-23 18:09:09
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status time-taken
GET /WIPS/WIPSDataService.svc/tCAPSCapacityTemplateHeader $filter=FACILITY%20eq%20'2400'&$orderby=FACILITY,TEMPLATE_NAME 80 - ::1 Microsoft+ADO.NET+Data+Services 200 0 0 45
2010-03-23 18:09:17 ::1 GET /WIPS/WIPSDataService.svc/tCAPSCapacity $filter=FACILITY%20eq%20'2400'%20and%20WORK_WEEK%20ge%20datetime'2010-03-21'%20and%20WORK_WEEK%20le%20datetime'2010-05-16'&$orderby=FACILITY,WORK_WEEK,RESOURCE_ID 80 - ::1 Microsoft+ADO.NET+Data+Services 200 0 0 48
2010-03-23 18:09:17 ::1 GET /WIPS/WIPSDataService.svc/tCAPSCapacityTemplate $filter=FACILITY%20eq%20'2400'&$orderby=FACILITY,RESOURCE_ID 80 - ::1 Microsoft+ADO.NET+Data+Services 200 0 0 31
2010-03-23 18:09:18 ::1 GET /WIPS/WIPSDataService.svc/tCAPSCapacity $filter=FACILITY%20eq%20'2400'%20and%20WORK_WEEK%20ge%20datetime'2010-03-21'%20and%20WORK_WEEK%20le%20datetime'2010-05-16'&$orderby=FACILITY,WORK_WEEK,RESOURCE_ID 80 - ::1 Microsoft+ADO.NET+Data+Services 200 0 0 6
2010-03-23 18:09:27 ::1 GET /WIPS/WIPSDataService.svc/tCAPSCapacityTemplateDetail $filter=TEMPLATE_ID%20eq%20'86017986-0AF0-4287-956A-BA569068D18E'&$orderby=GROUP_ID 80 - ::1 Microsoft+ADO.NET+Data+Services 200 0 0 21
2010-03-23 18:09:28 ::1 GET /WIPS/WIPSDataService.svc/tCAPSCapacityTemplateDetail $filter=TEMPLATE_ID%20eq%20'86017986-0AF0-4287-956A-BA569068D18E'&$orderby=GROUP_ID 80 - ::1 Microsoft+ADO.NET+Data+Services 200 0 0 4
2010-03-23 18:09:30 ::1 GET /WIPS/WIPSDataService.svc/tCAPSCapacityTemplateDetail(GROUP_ID='240009',TEMPLATE_ID='86017986-0AF0-4287-956A-BA569068D18E') - 80 - ::1 Microsoft+ADO.NET+Data+Services 200 0 0 5
2010-03-23 18:09:30 ::1 DELETE /WIPS/WIPSDataService.svc/tCAPSCapacityTemplateDetail(GROUP_ID='240009',TEMPLATE_ID='86017986-0AF0-4287-956A-BA569068D18E') - 80 - ::1 Microsoft+ADO.NET+Data+Services 405 0 0 1

Open in new window

0
blandyukCommented:
I'd start by adding the DELETE header to the whole site for now, obviously not going to leave it on there but see if it resolves your issue. Restart IIS once you have made the filter change to make sure it's been included.

IIS Error 405 is Method not Allowed, which is basicaly your DELETE header as IIS does not accept it as default due to security reasons obviously.
0
jmgroftAuthor Commented:
I added the DELETE verb to the entire site, although it didn't appear that it was necessary.  According to the blurb in Request Filtering: "Verbs that appear in the list and have Allowed set to False are blocked.  No other verbs are blocked."  And, of course, there was nothing in the list.  I added DELETE but it does not appear to have had any effect.  The DELETE verb is still blocked, but I'm not certain how that's happening.  

(I did notice that adding the filter at the site level did appear to filter down to the virtual directory as well because when I displayed the request filtering for the virtual directory, it showed the DELETE entry that I had made at the site level.  I also made sure that I stopped and restarted the server.)  Unfortunately, as I said, there was no effect.
0
jmgroftAuthor Commented:
Okay, I managed to get it to work.  I came across the following article:
http://www.shouldersofgiants.co.uk/Blog/post/2009/11/27/HTTP-Error-405-With-ASPNet-MVC-and-HTTP-PUT-on-IIS-75.aspx

Essentially, I turned off WebDAV using the web.config for my data service.  Now that strikes me as a brute force way to do it.  So far, though, it's the only thing that worked.  Request Filtering seemed to make absolutely no difference.  Neither did turning off Verb Filterning within the WebDAV Authoring Rules.  So I'm at a loss as to why DELETE was being restricted while WebDAV was turned on.  If anyone has any thoughts on why that would be, please let me know.

Also, now that I've gotten the DELETE to work for my data service, let's also move onto the next thing that was mentioned.  Why is it dangerous to enable the DELETE verb?  It appears to be the only way to enable records to be deleted through the WCF DataServices Entity Framework - unless I implement a service operation that invokes a stored procedure.  Is there a best practice here?
0
blandyukCommented:
Enabling DELETE, COPY and PUT means anyone can upload, copy and delete files on your server. I could simply upload a script file from which I could access your entire server and do what I wished with it :)
0
jmgroftAuthor Commented:
Okay, that makes sense if its enabled for the entire server with no restrictions (which I assume it is right now because I disabled WebDAV.)  Of course, for right now it's just a development version on my own laptop so not a problem.)  However, if it is only enabled via the request handlers for specific applications would that still be a security risk?  So, for example, if it's only enabled for .svc files, how can someone upload a file to cause a problem?  (I'm not arguing - just asking.)

Thanks for all your help.
John
0
blandyukCommented:
The problem is they can DELETE any of the *.svc files from the server :) Also, when using PUT, someone can simply PUT their file as an .svc file and simply MOVE, COPY it to another filename. If you are going to go down this route, I'd IP restrict it or require authentication.
0
jmgroftAuthor Commented:
Actually, given what you've explained to me, I'm thinking I probably won't go down this route.  Even though the application will be on an intranet and I'm quite certain that none of the users would have the first clue how to exploit the situation, I don't want to leave gaping security holes.  

From my perspective, I'm just trying to learn because, until recently I haven't had much opportunity to be exposed to web security.  If you can recommend a good book that discusses these kinds of issues, please let me know.  In the meantime, I'd like to pick your brain if you're okay with that.

Now, based on your last response, you said that someone can use the DELETE and PUT verbs to delete and update files on the server.  Certainly, that would be true if you've enabled those verbs for the entire virtual directory.  What I'm confused about is this:  If you haven't enabled the PUT/DELETE/MOVE/COPY verbs for the entire directory, but instead have restricted those via request filtering so that only .svc files can accept the PUT/DELETE verbs, wouldn't that mean that those two verbs would be ingored by anything other than a running .svc file?  If so, then my existing .svc file should be the only file that could accept the PUT/DELETE verb and would only do what I've allowed it to do.    Since PUT/DELETE/MOVE/COPY are not enabled for the entire virtual directory, no one has access to replace my .svc file with something that can do damage, correct?  Am I misunderstanding this?

Thanks,
John
0
blandyukCommented:
The best way to test this is to put it into practice. If you try the below HTTP header, see if it actually uploads the file. You can do this with telnet:

telnet www.somaindomain.com 80

Then copy/paste the below and it'll give you a server response:

PUT /WIPS/nasty-script.asp HTTP/1.1
Host: www.somedomain.com
Content-Length: 51
Accept: *.*
Connection: close

<%
Response.ReDirect("http://www.google.com/")
%>
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jmgroftAuthor Commented:
While I discovered the answer to my question on my own, these responses showed my why it was the wrong approach and how to test it.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
WCF

From novice to tech pro — start learning today.