Неверный запрос при попытке опубликовать в ASP .NET

#c# #asp.net #post #asp.net-web-api #get

Вопрос:

У меня довольно простая система: сервер ASP .NET Core, который размещен на domain.ru. В контроллере API у меня есть 2 метода:

     [HttpGet("{id}")]
    public string Get(int id)
    {
        try
        {
            using (FileStream fstream = new FileStream(string.Format(@"{0}data{1}.txt", _path, id.ToString()), FileMode.OpenOrCreate))
            {
                byte[] array = System.Text.Encoding.Default.GetBytes(id.ToString());
                fstream.Write(array, 0, array.Length);
                return "It's ok!";
            }
        }
        catch
        {
            return "Something went wrong";
        }
    }
    [HttpPost]
    public string Post(string resolvedString)
    {
        try
        {
            using (FileStream fstream = new FileStream(string.Format(@"{0}dataPost.txt", _path), FileMode.OpenOrCreate))
            {
                byte[] array = System.Text.Encoding.Default.GetBytes(resolvedString);
                fstream.Write(array, 0, array.Length);
                return "It's ok!";
            }
        }
        catch
        {
            return "Something went wrong";
        }
    }
 

Таким образом, в основном оба они просто создают текстовые файлы в каталоге _path. Часть, которую я не могу понять, — это когда я пытаюсь вызвать метод Get по url domain.ru/api/values/1 Я вижу файл, который был создан в каталоге _path, и у меня есть ответ «Все в порядке!». Вот как я называю Получить:

         var client = new HttpClient();
        client.BaseAddress = new Uri(uri);
        HttpResponseMessage response = await client.GetAsync("api/values/1");
        string result = await response.Content.ReadAsStringAsync();
        textBox1.Text = result.ToString();
 

Но когда я пытаюсь сделать то же самое с Почтой, я получаю либо Плохой запрос, когда я делаю это с помощью C#, либо «Что-то пошло не так», когда я делаю это с Почтальоном.
Вот так я называю Пост

         var client = new HttpClient();
        client.BaseAddress = new Uri(uri);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        MultipartFormDataContent content = new MultipartFormDataContent();
        StringContent str = new StringContent("1");
        content.Add(str);
        HttpResponseMessage response = await client.PostAsync("api/values/", content);
        string returnString = await response.Content.ReadAsStringAsync();
        MessageBox.Show(returnString);
 

Вот что показывает запрос, когда я пытаюсь вручную отладить это

And the most fun part. When I try to do all the same actions when my server is hosted on IIS (localserver) it works just fine! I’ really don’t know what I am doing wrong. Please, help.

UPD. Thanks to Jonathan, I asked my hoster to disable ModSecurity in Plesk and the above code started to work after replacing [HttpPost] by [HttpPost(«{resolvedString}»)]. So far so good!

Then I tried to send a zip archive to the server. Here is the server’s controller code:

     [HttpPost]
    public string ImportZip(IFormFile file)
    {
        DirectoryInfo dirInfo = new DirectoryInfo(_extractPath);
        try
        {
            foreach (FileInfo myfile in dirInfo.GetFiles())
            {
                myfile.Delete();
            }
            string path = _path   "tmp.zip";
            if (Request.HasFormContentType)
            {
                var form = Request.Form;
                foreach (var formFile in form.Files)
                {
                    using (var fileStream = new FileStream(path, FileMode.Create))
                    {
                        formFile.CopyTo(fileStream);
                    }
                    ZipFile.ExtractToDirectory(_path   "tmp.zip", _extractPath);
                }
            }
            return "It's OK! At least we've entered the method.";
        }
        catch
        {
            return "Oh no no no...";
        }

    }
 

И именно так я называю это от клиента:

         string filepath = _zipFile;
        string filename = _fileName;
        var client = new HttpClient();
        client.BaseAddress = new Uri(uri);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        MultipartFormDataContent content = new MultipartFormDataContent();
        ByteArrayContent fileContent = new ByteArrayContent(File.ReadAllBytes(filepath));
        content.Add(fileContent, "file", filename);
        HttpResponseMessage response = await client.PostAsync("File/ImportZip/", content);
        string result = await response.Content.ReadAsStringAsync();
        textBox1.Text = resu<
 

Еще раз, это работает так, как должно работать, когда я запускаю как сервер, так и клиент на своем компьютере. Я могу видеть загруженный архив и извлеченные файлы в каталогах назначения.
Но когда я загружаю свой сервер на хостинг и пытаюсь выполнить свой запрос еще раз, я получаю ту же ошибку:
пример ошибки

Комментарии:

1. Блокирует ли Plesk modsecurity сообщение? см.: plesk.com/blog/various/modsecurity-comprehensive-guide

2. Отключите отладку try/catch и try8, так как вы получите исключение в visual studio.

3. @AliK, я не могу отлаживать свой код, когда он размещен.

4. @Джонатан, спасибо, это сработало для одного случая. Но это либо вообще не работает, либо я совершаю какие-то глупые ошибки, которых не вижу.

5. Что ж, единственная ошибка, которую вы опубликовали, показывает, что ваш запрос столкнулся с проблемой безопасности Plesk. Какие еще ошибки вы получаете?

Ответ №1:

Что ж, похоже, я сам нашел ответ. Оставлю его здесь, чтобы он мог кому-то помочь (возможно, мне в будущем).

Код метода отправки клиента:

         string uri = "https://example.com/controller/action/";
        string zipFile = @"C:PathToYourFile.txt";
        string response;
        using (WebClient client = new WebClient())
        {
            response = Encoding.Default.GetString(client.UploadFile(uri, zipFile));
        }
        MessageBox.Show(response);
 

Здесь мы просто составляем запрос и отправляем файл. Путь и URL-адрес жестко заданы для ex.

Код метода сохранения сервера:

 [HttpPost]
    public string ImportZip(IFormFile file)
    {
        try
        {
            string path = _path   "tmp.zip";
            if (Request.HasFormContentType)
            {
                var form = Request.Form;
                foreach (var formFile in form.Files)
                {
                    using (var fileStream = new FileStream(path, FileMode.Create))
                    {
                        formFile.CopyTo(fileStream);
                    }
                }
                return "Done";
            }
            return "Empty request";
        }
        catch
        {
            return "No access";
        }
    }
 

Пока я отправляю только один файл, а также знаю его расширение и хочу, чтобы он назывался «tmp», я жестко кодирую его имя и расширение. Вы можете использовать имя/расширение файла по умолчанию, чтобы сохранить его как есть.
Затем я сохраняю все файлы в запросе в выбранном каталоге _path.

В принципе, вот и все.