我已经实现了创建WebApi本身,我可以从浏览器中浏览它并获得输出。
对我不起作用的是我试图从MVC Controller中使用WebAPI,并且我已经编写了用于在我的“cshtml”视图中调用WebAPI的代码。
但它不起作用,因为我在加载页面时遇到错误,我知道我做错了。所以第一个问题是:我正确地做了这个,还是在MVC项目中创建一个WebAPI部分然后尝试从控制器在同一个MVC项目中使用它是完全错误的?
答案 0 :(得分:2)
要回答您的问题,它实际上是“按设计”,并建议您将WebAPI和MVC客户端放在同一个项目中。这就是您在MVC项目中同时拥有RouteConfig.cs
和WebApiConfig.cs
的原因。 RouteConfig.cs
适用于您的MVC控制器,WebApiConfig.cs
显然适用于您的Api控制器。
让两个人在同一个项目中很容易。我所做的是在我的根目录中添加一个名为“API”的文件夹,并将所有的WebAPI控制器放在那里。请记住,我相信你知道,WebAPI控制器和MVC控制器之间的唯一区别是WebAPI控制器继承了ApiController
System.Web.Http
的一部分(我相信)而MVC控制器继承Controller
,它是System.Web.MVC
的一部分。
以下是对您的WebAPI FROM 进行GET / PUT / DELETE / POST请求 TO 的正确方法。它是否在同一个项目中并不重要,因为您在控制器的构造函数中指定了WebAPI URL。如果您的WebAPI与前端MVC应用程序位于不同的服务器上,则需要启用CORS支持,这是WebAPI版本2及更高版本中提供的功能。
这是从前端MVC客户端调用WebAPI的正确方法。
在您的控制器页面中,删除任何与DbContext,Entity Framework等有关的内容。原因是默认情况下,控制器希望通过调用DbContext来执行CRUD操作,我们不希望这样。我们想要调用WebAPI来执行此操作。当我提到“Controller”时,我指的是MVC控制器,而不是WebAPI控制器。
首先,在MVC控制器中声明一些成员变量。 MVC控制器的其余部分将使用这些:
HttpClient client = new HttpClient();
HttpResponseMessage response = new HttpResponseMessage();
Uri contactUri = null;
在MVC控制器中,为控制器创建一个构造函数,如下所示:
public ContactController()
{
// set base address of WebAPI depending on your current environment
// the URL below, if the API is in the same project, will be something
// like "http://server/YourProjectName" - replace server with either
// "localhost", etc.
client.BaseAddress = new Uri("http://server/YourAPI/");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
使用以下内容替换Index操作的代码。请注意,唯一相关的部分是client.GetAsync()
调用和var contacts
分配。对于此问题的上下文,其他所有内容都不是必需的。 client.GetAsync()
中的值应该是您的控制器的名称,由您在WebApiConfig.cs中设置的任何自定义路由预先添加 - 在我的情况下,我在路由中添加了api
部分以区分API调用和普通调用:
public ActionResult Index()
{
response = client.GetAsync("api/contact").Result;
if (response.IsSuccessStatusCode)
{
var contacts = response.Content.ReadAsAsync<IEnumerable<Contact>>().Result;
return View(contacts);
}
else
{
// add something here to tell the user hey, something went wrong
return RedirectToAction("Index");
}
}
使用以下内容替换“创建”操作(HttpPost操作)。同样,唯一重要的部分是client.PostAsJsonAsync()
部分 - 这就是调用WebAPI的POST操作,在我的例子中,它会将新记录插入到数据库中:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Contact contact)
{
// Create a new product
response = client.PostAsJsonAsync("api/contact", contact).Result;
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
// add something here to tell the user hey, something went wrong
return RedirectToAction("Index");
}
}
使用以下内容替换“编辑”操作(非HttpPost操作)。这有点棘手,因为为了编辑,你必须首先检索记录,所以基本上,编辑的HttpPost版本将包含一些类似的代码,另外一行代码执行编辑POST(PUT)。下面,我们通过传递特定的记录ID来获取WebAPI的响应。所以,就像Index(GET)一样,我们只做传递ID的事情,所以我们只返回一条记录。然后,我们将响应转换为可以在视图中操作的实际对象:
public ActionResult Edit(int id = 0)
{
response = client.GetAsync(string.Format("api/contact/{0}", id)).Result;
Contact contact = response.Content.ReadAsAsync<Contact>().Result;
if (contact == null)
{
return HttpNotFound();
}
return View(contact);
}
使用以下内容替换编辑操作(HttpPost操作)。下面,我们通过调用client.GetAsync()
并将主键作为参数(contact_id)传递来获取要编辑的记录。然后,我们从该响应中获取RequestUri并保存它。然后,我们调用client.PutAsJsonAsync()
并传入Uri.PathAndQuery(我们刚刚保存的内容)以及要编辑的对象。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Contact contact)
{
response = client.GetAsync(string.Format("api/contact/{0}", contact.contact_id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.PutAsJsonAsync(contactUri.PathAndQuery, contact).Result;
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
else
{
// add something here to tell the user hey, something went wrong
return RedirectToAction("Index");
}
}
使用以下内容替换Delete操作(非HttpPost操作)。所以,我们再次通过调用client.GetAsync()
并将其转换为我的应用知道的实际对象,从数据库中获取记录。
public ActionResult Delete(int id = 0)
{
response = client.GetAsync(string.Format("api/contact/{0}", id)).Result;
Contact contact = response.Content.ReadAsAsync<Contact>().Result;
if (contact == null)
{
return HttpNotFound();
}
return View(contact);
}
最后,使用以下内容替换Delete操作(HttpPost操作)。同样,我们正在做类似于Edit操作的操作。我们将要删除的记录,将其转换为对象,然后将该对象传递到client.DeleteAsync()
调用,如下所示。
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
response = client.GetAsync(string.Format("api/contact/{0}", id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.DeleteAsync(contactUri).Result;
return RedirectToAction("Index");
}