18

How to make the View returned by the controller and generated by Razor get the data from the api i want to keep the razor engine view and use the api the original mvc controller returns the view with the data as parameter now i want the data from the api

MVC controller

public class ProductController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

Api Controller

public class ProductsController : ApiController
{
    private ApplicationDbContext db = new ApplicationDbContext();

    // GET api/Products
    public IEnumerable<Product> GetProducts()
    {
        return db.Products;
    }
}

Model:

@model IEnumerable<WebApplication2.Models.Product>

@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
    <th>
        @Html.DisplayNameFor(model => model.Name)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.Category)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.Price)
    </th>
    <th></th>
</tr>

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.Name)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Category)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Price)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
        @Html.ActionLink("Details", "Details", new { id=item.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id=item.Id })
    </td>
</tr>
}
</table>
1
  • I'm on a project to learn the roles of M,V, and C in Razor. I believe what you label "Model:" should be labeled View instead. Model in this example is only a list of Models.Product objects which the Controller produces. Commented Jan 13, 2020 at 15:35

4 Answers 4

21

You could send an HTTP request to your Web API controller from within the ASP.NET MVC controller:

public class ProductController : Controller
{
    public ActionResult Index()
    {
        var client = new HttpClient();
        var response = client.GetAsync("http://yourapi.com/api/products").Result;
        var products = response.Content.ReadAsAsync<IEnumerable<Product>>().Result;
        return View(products);
    }
}

Also if you can take advantage of the .NET 4.5 async/await it is strongly recommended to do so to avoid blocking calls:

public class ProductController : Controller
{
    public async Task<ActionResult> Index()
    {
        var client = new HttpClient();
        var response = await client.GetAsync("http://yourapi.com/api/products");
        var products = await response.Content.ReadAsAsync<IEnumerable<Product>>();
        return View(products);
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

i created a html client that calls the api using url /api/products it worked but there is a problem with the ("yourapi.com/api/products") what should i put here exactly ??
You should put the url of your Web API endpoint returning the list of products.
thank you !! Can I replace the url by @Url.Action ??
That would depend on whether the Web API is hosted in the same ASP.NET host as your ASP.NET MVC application. Otherwise you cannot expect the client application to know anything about the routing configured on the server side. If both applications are hosted in the same host you could use the RouteUrl helper: string productsUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "products" });.
Be careful when you start using load balancers or reverse proxies that get assigned the yourapi.com DNS name and that have specific rules to block too many requests from a single client or when rewriting requests and such (SSL offloading is one such example). Also be mindful of the performance impact of roundtrips over the network in such case.
|
21

Read here on how to use the Razor view engine inside your Web API controller. The interesting part is using the RazorEngine NuGet package to do the heavy lifting.

1 Comment

Your answer is definitely better answer than doing HTTP request from MVC to API controller. I do not know why that answer has so many upvotes but from performance pov it is nonsense to do it.
1

The basis of the link supplied by twoflower is to have your handlers create and return an instance of a custom IHttpActionResult implementation. A simplified example is shown below:

public class TestHttpActionResult : IHttpActionResult
{
    private readonly HttpRequestMessage _request;
    private readonly string _responseString;

    public TestHttpActionResult(HttpRequestMessage request, string responseString)
    {
        _request = request;
        _responseString = responseString;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = _request.CreateResponse(HttpStatusCode.Created);
        response.Content = new StringContent(_responseString);
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
        return Task.FromResult(response);
    }
}

Comments

0

You can return a string in response by using

return Ok(".....");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.