前端 ASP.NET MVC4 作为一个项目,ASP.NET Web API 作为同一解决方案中的另一个项目 - 如何从前端调用 WebAPI?
Posted
技术标签:
【中文标题】前端 ASP.NET MVC4 作为一个项目,ASP.NET Web API 作为同一解决方案中的另一个项目 - 如何从前端调用 WebAPI?【英文标题】:Front end ASP.NET MVC4 as one project, and an ASP.NET Web API as another project in same solution - how to call WebAPI from front end? 【发布时间】:2013-09-20 15:39:28 【问题描述】:我有一个 ASP.NET MVC4 前端作为我的解决方案中的一个项目,以及一个单独的 ASP.NET Web API 作为同一解决方案中的另一个项目。 Web API 将包含我所有的 CRUD 操作。
2 个问题
-
如何从我的前端调用我的 Web API 来执行 CRUD 操作?我在我的 Web API 项目中定义了我的实体数据模型,我需要将我的前端视图绑定到它,我该怎么做?
一旦将其部署到我的 Web 服务器上,前端将驻留在一个服务器上,而 Web API 将驻留在另一台服务器上(该服务器拥有我们的大部分 Web 服务)。所以,我想沿着同样的思路,一旦部署,我将如何从我的前端调用 Web API?我知道 Web API 只是通过 HTTP 请求调用,但就将我的模型(在我的 Web API 项目中定义)传递到我的视图(在我的前端项目中)而言,我该怎么做?
【问题讨论】:
【参考方案1】:虽然凯文是对的,但我以非 Ajax 的方式做到了这一点。请记住,我正在处理 JSON 数据,所以它以 JSON 为中心。
在您的控制器页面中,删除与 DbContext、Entity Framework 等有关的任何内容。原因是默认情况下,控制器将希望通过调用 DbContext 来执行 CRUD 操作,而我们不希望这样。我们希望调用 WebAPI 来执行此操作。
首先,在控制器中声明一些成员变量。控制器的其余部分将使用这些:
HttpClient client = new HttpClient();
HttpResponseMessage response = new HttpResponseMessage();
Uri contactUri = null;
在您的控制器中,为您的控制器创建一个构造函数,如下所示:
public ContactController()
// set base address of WebAPI depending on your current environment
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");
将 Create 操作(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");
将 Edit 操作(非 HttpPost 操作)替换为以下内容。这有点棘手,因为为了进行编辑,您必须先检索记录,所以基本上,HttpPost 版本的 Edit 将包含一些类似的代码,还有一行代码执行编辑 POST (PUT)。下面,我们通过向 WebAPI 传递一个特定的记录 ID 来获取响应。因此,就像 Index (GET) 一样,我们只是在做同样的事情,只传递 ID,所以我们只取回一条记录。然后,我们将响应转换为可以在 View 中操作的实际对象:
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);
将 Edit 操作(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");
【讨论】:
【参考方案2】:您可以使用 jQuery ajax method 从客户端调用您的 Web API。但由于您是从部署 Web API 的站点以外的站点调用的,因此您必须使用 JSONP 而不是 JSON。看看这个QA to see how you use JSONP with Web API。您的模型将作为 JSON 传递,您必须在客户端呈现,而不是使用 Razor 在服务器端呈现它。我会使用 Knockout 之类的东西在客户端上创建一个视图模型,它将您的模型绑定到客户端上的 html 元素。
【讨论】:
以上是关于前端 ASP.NET MVC4 作为一个项目,ASP.NET Web API 作为同一解决方案中的另一个项目 - 如何从前端调用 WebAPI?的主要内容,如果未能解决你的问题,请参考以下文章
新的 MVC 4 项目基于使用 Subsonic 作为 ORM 的 ASP.net 网络论坛应用程序......从哪里开始......?
如何在 Asp.Net MVC4 Razpr 视图中将操作链接作为图像?
快速开发之代码生成器(asp.net mvc4 + easyui + knockoutjs)