Вызов веб-API от контроллера MVC

У меня есть контроллер WebAPI в моем решении MVC5. В WebAPI есть метод, который возвращает все файлы в определенной папке в виде списка Json:

[{"name":"file1.zip", "path":"c:\\"}, {...}]

Из моего HomeController я хочу вызвать этот метод, преобразовать ответ Json в List<QDocument> и вернуть этот список в представление Razor. Этот список может быть пустым: [], если в папке нет файлов.

Это APIController:

public class DocumentsController : ApiController
{
    #region Methods
    /// <summary>
    /// Get all files in the repository as Json.
    /// </summary>
    /// <returns>Json representation of QDocumentRecord.</returns>
    public HttpResponseMessage GetAllRecords()
    {
      // All code to find the files are here and is working perfectly...

         return new HttpResponseMessage()
         {
             Content = new StringContent(JsonConvert.SerializeObject(listOfFiles), Encoding.UTF8, "application/json")
         };
    }               
}

Вот мой HomeController:

public class HomeController : Controller
{
     public Index()
     {
      // I want to call APi GetAllFiles and put the result to variable:
      var files = JsonConvert.DeserializeObject<List<QDocumentRecord>>(API return Json);
      }
 }

Наконец, это модель, если она вам нужна:

public class QDocumentRecord
{
      public string id {get; set;}
      public string path {get; set;}
   .....
}

Итак, как я могу выполнить этот вызов?

Ответ 1

Из моего HomeController я хочу вызвать этот метод и преобразовать ответ Json в List

Нет, нет. Вы действительно не хотите добавлять накладные расходы на HTTP-вызов и (де) сериализацию, когда код находится в пределах досягаемости. Это даже в той же сборке!

Ваш ApiController в любом случае идет против (моего предпочтительного) соглашения. Пусть он возвращает конкретный тип:

public IEnumerable<QDocumentRecord> GetAllRecords()
{
    listOfFiles = ...
    return listOfFiles;
}

Если вы этого не хотите, и вы абсолютно уверены, что вам нужно вернуть HttpResponseMessage, тогда все равно нет нужно беспокоиться о вызове JsonConvert.SerializeObject() самостоятельно:

return Request.CreateResponse<List<QDocumentRecord>>(HttpStatusCode.OK, listOfFiles);

Опять же, вам не нужна бизнес-логика в контроллере, поэтому вы извлекаете это в класс, который выполняет вашу работу:

public class FileListGetter
{
    public IEnumerable<QDocumentRecord> GetAllRecords()
    {
        listOfFiles = ...
        return listOfFiles;
    }
}

В любом случае, вы можете вызвать этот класс или ApiController непосредственно с вашего контроллера MVC:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var listOfFiles = new DocumentsController().GetAllRecords();
        // OR
        var listOfFiles = new FileListGetter().GetAllRecords();

        return View(listOfFiles);
    }
}

Но если вы действительно должны действительно выполнить HTTP-запрос, вы можете использовать HttpWebRequest, WebClient, HttpClient или RestSharp, для всех из которых существует множество обучающих программ.

Ответ 2

Он очень поздно здесь, но думал делиться ниже кода. Если у нас есть наш WebApi как совсем другой проект в том же решении, то мы можем назвать то же самое с контроллера MVC, как показано ниже

public class ProductsController : Controller
    {
        // GET: Products
        public async Task<ActionResult> Index()
        {
            string apiUrl = "http://localhost:58764/api/values";

            using (HttpClient client=new HttpClient())
            {
                client.BaseAddress = new Uri(apiUrl);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                HttpResponseMessage response = await client.GetAsync(apiUrl);
                if (response.IsSuccessStatusCode)
                {
                    var data = await response.Content.ReadAsStringAsync();
                    var table = Newtonsoft.Json.JsonConvert.DeserializeObject<System.Data.DataTable>(data);

                }


            }
            return View();

        }
    }

Ответ 3

Почему бы вам просто не переместить код, который у вас есть в вызовах ApiController - DocumentsController, в класс, который вы можете вызвать из своего HomeController и DocumentController. Вытащите это в класс, который вы вызываете из обоих контроллеров. Этот материал в вашем вопросе:

//Весь код для поиска файлов здесь и работает отлично...

Нет смысла вызывать контроллер API с другого контроллера на том же веб-сайте.

Это также упростит код, когда вы вернетесь к нему в будущем, у вас будет один общий класс для поиска файлов и выполнения этой логики там...

Ответ 4

Хорошо, вы можете сделать это много способов... одним из них является создание HttpRequest. Я бы посоветовал вам не называть свой собственный webapi из вашего собственного MVC (идея избыточна...), но здесь в конце учебника.

Ответ 5

контроллер:

    public JsonResult GetProductsData()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("http://localhost:5136/api/");
            //HTTP GET
            var responseTask = client.GetAsync("product");
            responseTask.Wait();

            var result = responseTask.Result;
            if (result.IsSuccessStatusCode)
            {
                var readTask = result.Content.ReadAsAsync<IList<product>>();
                readTask.Wait();

                var alldata = readTask.Result;

                var rsproduct = from x in alldata
                             select new[]
                             {
                             Convert.ToString(x.pid),
                             Convert.ToString(x.pname),
                             Convert.ToString(x.pprice),
                      };

                return Json(new
                {
                    aaData = rsproduct
                },
    JsonRequestBehavior.AllowGet);


            }
            else //web api sent error response 
            {
                //log response status here..

               var pro = Enumerable.Empty<product>();


                return Json(new
                {
                    aaData = pro
                },
    JsonRequestBehavior.AllowGet);


            }
        }
    }

    public JsonResult InupProduct(string id,string pname, string pprice)
    {
        try
        {

            product obj = new product
            {
                pid = Convert.ToInt32(id),
                pname = pname,
                pprice = Convert.ToDecimal(pprice)
            };



            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://localhost:5136/api/product");


                if(id=="0")
                {
                    //insert........
                    //HTTP POST
                    var postTask = client.PostAsJsonAsync<product>("product", obj);
                    postTask.Wait();

                    var result = postTask.Result;

                    if (result.IsSuccessStatusCode)
                    {
                        return Json(1, JsonRequestBehavior.AllowGet);
                    }
                    else
                    {
                        return Json(0, JsonRequestBehavior.AllowGet);
                    }
                }
                else
                {
                    //update........
                    //HTTP POST
                    var postTask = client.PutAsJsonAsync<product>("product", obj);
                    postTask.Wait();
                    var result = postTask.Result;
                    if (result.IsSuccessStatusCode)
                    {
                        return Json(1, JsonRequestBehavior.AllowGet);
                    }
                    else
                    {
                        return Json(0, JsonRequestBehavior.AllowGet);
                    }

                }




            }


            /*context.InUPProduct(Convert.ToInt32(id),pname,Convert.ToDecimal(pprice));

            return Json(1, JsonRequestBehavior.AllowGet);*/
        }
        catch (Exception ex)
        {
            return Json(0, JsonRequestBehavior.AllowGet);
        }

    }

    public JsonResult deleteRecord(int ID)
    {
        try
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://localhost:5136/api/product");

                //HTTP DELETE
                var deleteTask = client.DeleteAsync("product/" + ID);
                deleteTask.Wait();

                var result = deleteTask.Result;
                if (result.IsSuccessStatusCode)
                {

                    return Json(1, JsonRequestBehavior.AllowGet);
                }
                else
                {
                    return Json(0, JsonRequestBehavior.AllowGet);
                }
            }



           /* var data = context.products.Where(x => x.pid == ID).FirstOrDefault();
            context.products.Remove(data);
            context.SaveChanges();
            return Json(1, JsonRequestBehavior.AllowGet);*/
        }
        catch (Exception ex)
        {
            return Json(0, JsonRequestBehavior.AllowGet);
        }
    }