send a json file using ASP.net web api - asp.net-web-api

I was using this get method
public object Get()
{
string allText = System.IO.File.ReadAllText(#"c:\data.json");
object jsonObject = JsonConvert.DeserializeObject(allText);
return jsonObject;
}
but I got this error
NotSupportedException: The collection type 'Newtonsoft.Json.Linq.JObject' is not supported.
I also tried this method
public HttpResponseMessage Get()
{
var stream = new FileStream(#"c:\data.json", FileMode.Open);
var result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return result;
}
The error I got was
CS1061:'HttpRequest' does not contain a definition for 'CreateResponse' and no accessible extension method 'CreateResponse' accepting a first argument of type 'HttpRequest' could be found (are you missing a using directive or an assembly reference?)
How can I fix it? Also Is there any other way I can solve it?
Thanks in advance

You need to add a reference the System.Web.dll for HttpResponseMessage Get() to work.
Add a reference to System.Web.dll. This assembly is also available in the
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2
public HttpResponseMessage Get()
{
var stream = new FileStream(#"c:\data.json", FileMode.Open);
var result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return result;
}

Right click on References, then select Add References, then browse to System.Web.dll

Related

authorization required when create pdf file

I am trying to generate pdf file using c# web api using the following code :
i have tried to change in the web.config but it didn't help.
[HttpGet]
public HttpResponseMessage Generate()
{
var stream = new MemoryStream();
// processing the stream.
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.ToArray())
};
result.Content.Headers.ContentDisposition = new
System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "CertificationCard.pdf"
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
I expected download pdf directly to my local disk but non worked.

Returning binary data with web api

I have the following controller method which returns a byte array.
public async Task<HttpResponseMessage> Get()
{
var model = new byte[] { 1, 2, 3 };
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(new MemoryStream(model));
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;
}
I think this is an older way of implementing this functionality with web api. Is there a more "modern" version?
For example, is returning a Task<IHttpActionResult> the preferred way now? And if so, what would be the code to return the byte array from above?
As the comment pointed out. I dont think there is a new way to do this. But if you would like to return an IHttpActionResult instead, there is a base method that returns a ResponseMessageResult:
public IHttpActionResult Get()
{
var model = new byte[] { 1, 2, 3 };
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(new MemoryStream(model))
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return ResponseMessage(result);
}
Also, to return binary data in AspNetCore WebApi2 if anyone needs it:
[Route("api/v1/export/excel")]
[HttpGet]
public IActionResult GetAsExcel()
{
var exportStream = new MemoryStream();
_exportService.ExportAllToExcel(exportStream);
// Rewind the stream before we send it.
exportStream.Position = 0;
return new FileStreamResult(exportStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}

WebApi: Reading errors

I've got a simple web api which is consumed from a mvc project, I keep on getting the 'Response status code does not indicate success' and was wondering how would I get the response body from the error, I can see the error within a rest viewer but can't navigate through to the error. This is the following code within the MVC app
public ActionResult Index()
{
try
{
var uri = "http://localhost:57089/api/values";
using (var client = new HttpClient())
{
Task<string> response = client.GetStringAsync(uri);
object result = JsonConvert.DeserializeObject(response.Result);
return (ActionResult) result;
}
}
catch (Exception ex)
{
return Content(ex.ToString());
}
return View();
}
Within the API controller I'm sending a bad request, here's the code
public IHttpActionResult Get()
{
return BadRequest("this is a very bad request " + System.DateTime.Now.ToUniversalTime());
}
I've tried to use WebException, HttpRequestException as exceptions to catch the error with no luck.
I can see the response body within the rest viewer
I want to be able to navigate to the Error Message so I can pass that to the client (which later will be changed to a guid).
[EDITED]
I've got a solution without using GetStringAsync, but wanted to use that if possible.
Here's the solution
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(url);
HttpResponseMessage responseMessage = httpClient.GetAsync("").Result;
if (responseMessage.IsSuccessStatusCode) return Content(responseMessage.ToString());
var a = responseMessage.Content.ReadAsStringAsync().Result;
var result = JsonConvert.DeserializeObject<HttpError>(a);
object value = "";
return Content(result.TryGetValue("ErrorMessage", out value) ? value.ToString() : responseMessage.ToString());
Is there a better way?
Using WebException you should be able to get to the ResponseStream and the custom error message like this:
catch (WebException e)
{
var message = e.Message;
using (var reader = new StreamReader(e.Response.GetResponseStream()))
{
var content = reader.ReadToEnd();
}
}
Hope that helps.

Do Assemblies have to be physical files? - WepAPI

We have an MVC UI that will generically draw itself based on data types it gets from the WebAPI. On App start of the ui I call into my WebApi to pull the "LeadTypes" down in a list of Assemblies List using binary formatter to serialize and deserialize. Problem is, when the references are removed from the UI, the deserializer blows up saying it cannot find InstallmentLoan, version 1.0.0.0 or one of its dependencies. Well there are no dependencies other than system, these are just basic models with custom data annotations, etc. The goal is to not have any of our types referenced on the UI.
Error "Could not load file or assembly 'LeadGenFramework.Entity.LeadType.InstallmentLoan, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
There has to be a clever way to use and reference in memory assemblies without having the physical file. What I don't understand is why is it looking for a file if I have it in memory?
Any pointers would be great!
Here is the FusionLog:
=== Pre-bind state information ===
LOG: DisplayName = LeadGenFramework.Entity.LeadType.InstallmentLoan, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown)
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Users\charbaugh\AppData\Local\Temp\tmp8271.tmp
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan.DLL.
LOG: Attempting download of new URL file:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan/LeadGenFramework.Entity.LeadType.InstallmentLoan.DLL.
LOG: Attempting download of new URL file:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan.EXE.
LOG: Attempting download of new URL file:///E:/MainTrunk2/LeadGenFramework-Copy/trunk/LeadGenFramwork.Web.Api.RestClient.Test/bin/Debug/LeadGenFramework.Entity.LeadType.InstallmentLoan/LeadGenFramework.Entity.LeadType.InstallmentLoan.EXE.
You will have to get the assemblies from somewhere, for that you will need to stream the assembly content and call assembly.load(byte[] rawAssembly).
Ok, I figured this out. I was using reflections to get the assembly and then serializing the Assembly type. Assembly only provides property information for the physical file assembly and it does not contain an entire graph of the file. I hope this helps someone, lesson learned!
So I just used this on the controller and then the revers on the client.
public MemoryStream Get()
{
List<MemoryStream> leadTypeAssemblyStreams = new List<MemoryStream>();
foreach (string dllAssembly in _leadTypeNamespaces)
{
using (MemoryStream ms = new MemoryStream())
{
string filename = dllAssembly;
if (!filename.Contains(".dll"))
filename = filename + ".dll";
using (FileStream file = new FileStream(AssemblyDirectory + "\\" + filename, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms.Write(bytes, 0, (int)file.Length);
file.Close();
leadTypeAssemblyStreams.Add(ms);
ms.Close();
}
}
}
return new MemoryStream(SerializeObj(leadTypeAssemblyStreams));
}
internal static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
internal static byte[] SerializeObj(object obj)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
byte[] bytes = stream.ToArray();
stream.Close();
return bytes;
}
}
Now, I can just call the GetDeserializedFileStreamPaths(stream) and it will return a physical path to the files that were streamed from the WebApi. Here is my WebApiClient class the UI will reference.
public class LFGWebApiClientHelpers
{
public List<Type> GetLeadTypes(Stream stream)
{
List<string> assembliesFilePath = GetDeserializedFileStreamPaths(stream);
List<Assembly> assemblies = new List<Assembly>();
foreach (string filePath in assembliesFilePath)
{
assemblies.Add(Assembly.LoadFile(filePath));
}
List<Type> leadTypes = new List<Type>();
foreach (Assembly asm in assemblies)
{
Type leadType = asm.GetTypes().Where(x => x.GetCustomAttributes(typeof(WebApiExportedTypeAttribute), false).Length > 0).FirstOrDefault(x => x.Name.Contains("Lead"));
leadTypes.Add(leadType);
}
return leadTypes;
}
private static List<string> GetDeserializedFileStreamPaths(Stream stream)
{
try
{
List<string> assembliesPath = new List<string>();
IFormatter formatter = new BinaryFormatter();
List<MemoryStream> leadTypeAssemblyStreams = formatter.Deserialize(stream) as List<MemoryStream>;
int fileNumber = 1;
string leadTypeAsseblyDirectory = AssemblyDirectory.Replace("bin", "DownloadedLeadTypeAssemblies");
if (!Directory.Exists(leadTypeAsseblyDirectory))
Directory.CreateDirectory(leadTypeAsseblyDirectory);
try
{
if (leadTypeAssemblyStreams == null)
throw new Exception("Lead type assembly stream cannot be null.");
foreach (MemoryStream leadTypeAssemblyStream in leadTypeAssemblyStreams)
{
string localFileLocation = leadTypeAsseblyDirectory +
string.Format("\\LeadType{0}.dll", fileNumber);
//add path for return type
assembliesPath.Add(localFileLocation);
using (
FileStream file = new FileStream(localFileLocation, FileMode.Create, FileAccess.Write))
{
leadTypeAssemblyStream.WriteTo(file);
leadTypeAssemblyStream.Close();
}
fileNumber++;
}
}
catch (Exception ex)
{
throw new LGFException().SetMessage(ex);
}
stream.Close();
return assembliesPath;
}
catch (Exception ex)
{
throw new LGFException().SetMessage(ex, "There was a problems during the deserializtion of LeadTypes.");
}
}
private static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
}

ASP.Net WebAPI Return CSS

I need to write a Web API method that return result as CSS plain text and not the default XML or JSON, Is there a specific provider that I need to use?
I tried using the ContentResult class (http://msdn.microsoft.com/en-us/library/system.web.mvc.contentresult(v=vs.108).aspx) but no luck.
Thanks
You should bypass the content negotiation which means that you should return a new instance of HttpResponseMessage directly and set the content and the content type yourself:
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(".hiddenView { display: none; }", Encoding.UTF8, "text/css")
};
Using the answers here as inspiration. You should be able to do something as simple as this:
public HttpResponseMessage Get()
{
string css = #"h1.basic {font-size: 1.3em;padding: 5px;color: #abcdef;background: #123456;border-bottom: 3px solid #123456;margin: 0 0 4px 0;text-align: center;}";
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent(css, Encoding.UTF8, "text/css");
return response;
}
Can you return a HttpResponseMessage, get the file and just return the stream? Something like this seems to work....
public HttpResponseMessage Get(int id)
{
var dir = HttpContext.Current.Server.MapPath("~/content/site.css"); //location of the template file
var stream = new FileStream(dir, FileMode.Open);
var response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(stream)
};
return response;
}
Although I would add some error checking in there if the file doesn't exist etc....
And just to pile on for fun, here's a version that would work under self-host too assuming you store the .css as an embedded file that sits in the same folder as the controller. Storing it in a file in your solution is nice because you get all the VS intellisense. And I added a bit of caching because chances are this resource isn't going to change much.
public HttpResponseMessage Get(int id)
{
var stream = GetType().Assembly.GetManifestResourceStream(GetType(),"site.css");
var cacheControlHeader = new CacheControlHeaderValue { MaxAge= new TimeSpan(1,0,0)};
var response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
CacheControl = cacheControlHeader,
Content = new StreamContent(stream, Encoding.UTF8, "text/css" )
};
return response;
}
For anyone using AspNet Core WebApi you can simply do it like this
[HttpGet("custom.css")]
public IActionResult GetCustomCss()
{
var customCss = ".my-class { color: #fff }";
return Content(customCss, "text/css");
}

Resources