{"record":{"id":"d90e69b870d22dfc","repo":"dvf/blockchain","slug":"new-httpresponsemessage-httpstatuscode-methodnotallowed","errorCode":null,"errorMessage":"$\"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}\"","messagePattern":"\\$\"\\{new HttpResponseMessage\\(HttpStatusCode\\.MethodNotAllowed\\)\\}\"","errorType":"http","errorClass":null,"httpStatus":405,"severity":"error","filePath":"csharp/BlockChain/WebServer.cs","lineNumber":39,"sourceCode":"                    string json = \"\";\n                    if (path.Contains(\"?\"))\n                    {\n                        string[] parts = path.Split('?');\n                        path = parts[0];\n                        query = parts[1];\n                    }\n\n                    switch (path)\n                    {\n                        //GET: http://localhost:12345/mine\n                        case \"/mine\":\n                            return chain.Mine();\n\n                        //POST: http://localhost:12345/transactions/new\n                        //{ \"Amount\":123, \"Recipient\":\"ebeabf5cc1d54abdbca5a8fe9493b479\", \"Sender\":\"31de2e0ef1cb4937830fcfd5d2b3b24f\" }\n                        case \"/transactions/new\":\n                            if (request.HttpMethod != HttpMethod.Post.Method)\n                                return $\"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}\";\n\n                            json = new StreamReader(request.InputStream).ReadToEnd();\n                            Transaction trx = JsonConvert.DeserializeObject<Transaction>(json);\n                            int blockId = chain.CreateTransaction(trx.Sender, trx.Recipient, trx.Amount);\n                            return $\"Your transaction will be included in block {blockId}\";\n\n                        //GET: http://localhost:12345/chain\n                        case \"/chain\":\n                            return chain.GetFullChain();\n\n                        //POST: http://localhost:12345/nodes/register\n                        //{ \"Urls\": [\"localhost:54321\", \"localhost:54345\", \"localhost:12321\"] }\n                        case \"/nodes/register\":\n                            if (request.HttpMethod != HttpMethod.Post.Method)\n                                return $\"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}\";\n\n                            json = new StreamReader(request.InputStream).ReadToEnd();\n                            var urlList = new { Urls = new string[0] };","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/dvf/blockchain/blob/68066d648244ce2b7e2d1cbd16f9255363f94712/csharp/BlockChain/WebServer.cs#L21-L57","documentation":"The /transactions/new route only accepts POST; any other HTTP method (typically GET) is rejected with a 405 MethodNotAllowed response. However, the handler stringifies an HttpResponseMessage object, so instead of a real HTTP 405 status the server returns 200 OK whose body is the object's ToString() dump (e.g. 'StatusCode: 405, ReasonPhrase: Method Not Allowed'). Clients expecting JSON fail to parse the body and standard HTTP error handling never fires.","triggerScenarios":"Calling GET http://localhost:12345/transactions/new (or PUT/DELETE/HEAD) instead of POST with a JSON body like {\"Amount\":123,\"Recipient\":\"ebeabf5cc1d54abdbca5a8fe9493b479\",\"Sender\":\"31de2e0ef1cb4937830fcfd5d2b3b24f\"}. Opening the URL in a browser or a client configured with the wrong method hits this branch.","commonSituations":"Testing the endpoint in a browser address bar (always GET); copying a GET-based REST call pattern to a POST-only route; client libraries defaulting to GET when no body is set; Postman collections or API docs with the wrong verb; proxies or health checkers issuing GET probes.","solutions":["Send the request with method POST and a JSON transaction body","Fix the server to set the real status code on the HttpListenerResponse (response.StatusCode = 405) instead of interpolating an HttpResponseMessage into the returned string","Add an 'Allow: POST' header to the 405 response so clients learn the supported method","Ensure the client serializes Sender/Recipient/Amount as JSON, since a correct POST still needs a deserializable body"],"exampleFix":"// before\nif (request.HttpMethod != HttpMethod.Post.Method)\n    return $\"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}\";\n\n// after (server-side, respond with a real 405)\nif (request.HttpMethod != HttpMethod.Post.Method)\n{\n    response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;\n    response.Headers[\"Allow\"] = \"POST\";\n    return \"Method Not Allowed: use POST for /transactions/new\";\n}","handlingStrategy":"validation","validationCode":"// client-side check before sending\nusing (var req = new HttpRequestMessage(HttpMethod.Post, \"http://localhost:12345/transactions/new\"))\n{\n    req.Content = new StringContent(json, Encoding.UTF8, \"application/json\");\n    // send req; a 405 (or a 'StatusCode: 405' body) means the wrong method was used\n}","typeGuard":"static bool IsPostRequest(string method) =>\n    string.Equals(method, \"POST\", StringComparison.OrdinalIgnoreCase);","tryCatchPattern":"try\n{\n    var resp = await client.PostAsJsonAsync(url, trx);\n    if (resp.StatusCode == HttpStatusCode.MethodNotAllowed)\n        throw new InvalidOperationException(\"Use POST for /transactions/new\");\n}\ncatch (HttpRequestException ex)\n{\n    // log/handle the failed request; do not retry with the same verb\n}","preventionTips":["Always send POST with a JSON body to /transactions/new","Never test POST-only endpoints by pasting the URL into a browser","Check HTTP status codes, not the response body, when validating responses","Document each route's expected verb next to its path in the server"],"tags":["http","method-not-allowed","csharp","rest"],"backgroundTag":"http-error-status","analyzedSha":"68066d648244ce2b7e2d1cbd16f9255363f94712","analyzedAt":"2026-09-13T17:55:04.247Z","contentChangedAt":"2026-09-13T17:55:04.247Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}