Question

So i trying to lean web Api and implement in my project.

There are two things that i am not quite sure about

  1. I am trying to download pdf. My web api is in App Server and i am consuming it in my web server.

In my web api I have a method in controller

public class FilesController : ApiController
{        
    [ActionName("GetFile")]
    public HttpResponseMessage GetFile(string FileName, string CEQRNumber, string LatestMileStone)
    {
        var file = GetListofFilesByCEQRAndMilestone(FileName, CEQRNumber, LatestMileStone);
        var path = file.FilePath;
        var extension = file.FileExtention;
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new FileStream(path, FileMode.Open,FileAccess.ReadWrite);
        result.Content = new StreamContent(stream);

        if (extension == ".pdf")
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

        if (extension == ".xlsx" || extension == ".xls")
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

        if (extension == ".zip")
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("aapplication/zip");

        return result;
    }
}

Now i am not sure how to consume it. In my main mvc app in web server. I have an action method

public ActionResult GetFile(string fileName, string ceqrNum, string latestMS, string token)
{
    string url = "https://xxx/api/Files/GetFile/" + fileName + "/" + ceqrNum + "/" + latestMS;

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/pdf"));

            Task<String> response = client.GetStringAsync(url);

            // NOT SURE HOW TO CONVERT RESPONSE TO PDF

        }
}
  1. The second question i have is in routing: In webApiConfig.cs there is a default route set up

     public static void Register(HttpConfiguration config)
     {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
     }
    

I noticed that if i have to have diffrent parameters I have to add that in config

so I added

config.Routes.MapHttpRoute(
            name: "GetFileList",
            routeTemplate: "api/{controller}/{action}/{CEQRNumber}/{LatestMileStone}",
            defaults: new
            {
                CEQRNumber = UrlParameter.Optional,
                LatestMileStone = UrlParameter.Optional,
            }
        );

        config.Routes.MapHttpRoute(
            name: "GetFileForDownload",
            routeTemplate: "api/{controller}/{action}/{FileName}/{CEQRNumber}/{LatestMileStone}",
            defaults: new
            {
                Controller = "Files",
                FileName = UrlParameter.Optional,
                CEQRNumber = UrlParameter.Optional,
                LatestMileStone = UrlParameter.Optional
            }
        );

Now, can i have one default route that will work irrespective of parameters and action name or with every different action and parameters I have to write new route.

I will appreciate your answers. I am trying to understand the concepts of web api as this is the first time i am using it.

Thanks

Was it helpful?

Solution

A few comments -

  1. Don't open the file as read/write, read is plenty good.

  2. The second route is fine you don't need the first one, you can alternatively just post to the following route:

api/{controller}/{FileName}/{CEQRNumber}/{LatestMileStone}

and remove the [ActionName] attribute from the GetFiles.

Even simpler you can use the following route api/{controller} and pass the parameters as a query string.

so it's going to look like this

config.Routes.MapHttpRoute(
    routeTemplate: "api/{controller}"
);

Your url is going to look like:

http://xxx/api/Files?FileName=foo&CEQRNumber=bar,&LatestMileStone

The controller code:

public class FilesController : ApiController
{        
    public HttpResponseMessage GetFile(string FileName, string CEQRNumber, string LatestMileStone)
    {
        var file = GetListofFilesByCEQRAndMilestone(FileName, CEQRNumber, LatestMileStone);
        var path = file.FilePath;
        var extension = file.FileExtention;
        var result = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new FileStream(path, FileMode.Open,FileAccess.Read);
        result.Content = new StreamContent(stream);

        // do the header work
        return result;
    }
}

For your client code instead of ReadAsStringAsync use

 using (Stream responseStream = await response.Content.ReadAsStreamAsync())
 {
     // Read response stream
     await ReadResponseStreamAsync(responseStream, fileName);
 }

and don't forget to validate the response code on the client

For your comment on how to save a file from a stream:

 private void ReadResponseStreamAsync(stream responseStream, string fileName)
 {
      using (var fileStream = File.Create("C:\\Path\\To\\" + fileName))
      {
            responseStream.CopyTo(fileStream);
      }
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top