J'ai un contrôleur WebAPI dans ma solution de projet MVC5 . WebAPI a une méthode qui renvoie tous les fichiers d'un dossier spécifique sous forme de liste Json:
[{"name":"file1.Zip", "path":"c:\\"}, {...}]
À partir de mon HomeController, je souhaite appeler cette méthode, convertir la réponse Json en List<QDocument>
et renvoyer cette liste dans une vue Razor. Cette liste peut être vide: []
s'il n'y a aucun fichier dans le dossier.
C'est l'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")
};
}
}
Voici mon 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);
}
}
Enfin, voici le modèle au cas où vous en auriez besoin:
public class QDocumentRecord
{
public string id {get; set;}
public string path {get; set;}
.....
}
Alors, comment puis-je faire cet appel?
Depuis mon HomeController, je souhaite appeler cette méthode et convertir la réponse Json en liste
Non tu ne le fais pas. Vous ne voulez vraiment pas ajouter la surcharge d'un appel HTTP et d'une (dé) sérialisation lorsque le code est à portée de main. C'est même dans la même assemblée!
Votre ApiController va malgré tout à l'encontre de la convention (ma préférence) . Laissez-le retourner un type concret:
public IEnumerable<QDocumentRecord> GetAllRecords()
{
listOfFiles = ...
return listOfFiles;
}
Si vous ne le souhaitez pas et que vous êtes absolument certain de devoir retourner HttpResponseMessage
, il n'y a toujours aucun besoin de s'embêter à appeler JsonConvert.SerializeObject()
vous-même :
return Request.CreateResponse<List<QDocumentRecord>>(HttpStatusCode.OK, listOfFiles);
Là encore, vous ne voulez pas de logique métier dans un contrôleur, vous devez donc l'extraire dans une classe qui fait le travail pour vous:
public class FileListGetter
{
public IEnumerable<QDocumentRecord> GetAllRecords()
{
listOfFiles = ...
return listOfFiles;
}
}
Dans les deux cas, vous pouvez appeler cette classe ou ApiController directement à partir de votre contrôleur MVC:
public class HomeController : Controller
{
public ActionResult Index()
{
var listOfFiles = new DocumentsController().GetAllRecords();
// OR
var listOfFiles = new FileListGetter().GetAllRecords();
return View(listOfFiles);
}
}
Mais si vous devez vraiment, vraiment faire une requête HTTP, vous pouvez utiliser HttpWebRequest
, WebClient
, HttpClient
ou RestSharp
, pour lesquels de nombreux tutoriels existent.
Il est très tard ici, mais on pense partager le code ci-dessous . Si nous avons notre projet WebApi complètement différent de la même solution, nous pouvons appeler le même contrôleur MVC, comme ci-dessous.
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();
}
}
Pourquoi ne déplacez-vous pas simplement le code que vous avez dans les appels ApiController - DocumentsController vers une classe que vous pouvez appeler à la fois de HomeController et de DocumentController. Tirez ceci dans une classe que vous appelez des deux contrôleurs. Ce truc dans ta question:
// Tout le code pour trouver les fichiers est ici et fonctionne parfaitement ...
Il n'est pas logique d'appeler un contrôleur API à partir d'un autre contrôleur situé sur le même site Web.
Cela simplifiera également le code lorsque vous y reviendrez à l'avenir, vous aurez une classe commune pour rechercher les fichiers et y appliquer cette logique ...
eh bien, vous pouvez le faire de nombreuses façons ... L’une d’elles est de créer un HttpRequest . Je vous déconseille d'appeler votre propre webapi depuis votre propre MVC (l'idée est redondante ...) mais, voici un didacticiel de bout en bout .
Manette:
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);
}
}