I am using ASP.NET WEB API to upload image to server. But when i upload the source code of my web api to gearhost.com and make a post request. I am unable to post the image. This is my web api controller code:
[Route("upload")]
[HttpPost]
public async Task<string> Upload()
{
var ctx = HttpContext.Current;
var root = ctx.Server.MapPath("/uploads/");
var provider = new MultipartFormDataStreamProvider(root);
try
{
await Request.Content
.ReadAsMultipartAsync(provider);
foreach (var file in provider.FileData)
{
var name = file.Headers
.ContentDisposition
.FileName;
// remove double quotes from string.
name = name.Trim('"');
var localFileName = file.LocalFileName;
var filePath = Path.Combine(root, "files", name);
// File.Move(localFileName, filePath);
// SaveFilePathSQLServerADO(localFileName, filePath);
// SaveFileBinarySQLServerADO(localFileName, name);
// SaveFilePathSQLServerEF(localFileName, filePath);
SaveFileBinarySQLServerEF(localFileName, name, filePath);
if (File.Exists(localFileName))
File.Delete(localFileName);
}
}
catch
{
return "Error";
}
return "File uploaded successfully!";
}
public void SaveFileBinarySQLServerEF(string localFile, string fileName, string filePath)
{
// 1) Get file binary
byte[] fileBytes;
using (var fs = new FileStream(localFile, FileMode.Open, FileAccess.Read))
{
fileBytes = new byte[fs.Length];
fs.Read(fileBytes, 0, Convert.ToInt32(fs.Length));
}
// 2) Create a Files object
var file = new tblimage()
{
Data = fileBytes,
Names = fileName,
ContentType = filePath
};
// 3) Add and save it in database
using (var ctx = new coachEntities())
{
ctx.tblimages.Add(file);
ctx.SaveChanges();
}
}
Here is the successful call from localhost:
Image posted through localhost
However when deployed the same code and make request through postman then I get this error:
Image posted through live server
Maybe, "uploads" doesn't have write permission
Check the permission in your uploads folder.
Go to properties-- security
Give the read write permission.
Though it is not good idea to return the exception details in live code. As you are not maintaining log. For testing, Please return the exception details. Also, how are you getting the response like "unable to upload, try again" because it is not there in your code
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.
I'm using MEF in order to execute plugins code in my project.
1. I'm loading my dll sources :
public void AssembleComponents()
{
try
{
//Creating an instance of aggregate catalog. It aggregates other catalogs
var aggregateCatalog = new AggregateCatalog();
//Build the directory path where the parts will be available
var directoryPath =
string.Concat(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase)
.Split('\\').Reverse().Skip(4).Reverse().Aggregate((a, b) => a + "\\" + b)
, "\\", "ExportComponents\\Components");
string localPath = new Uri(directoryPath).LocalPath;
//Load parts from the available dlls in the specified path using the directory catalog
var directoryCatalog = new DirectoryCatalog(localPath, "*.dll");
//Load parts from the current assembly if available
var asmCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
//Add to the aggregate catalog
aggregateCatalog.Catalogs.Add(directoryCatalog);
aggregateCatalog.Catalogs.Add(asmCatalog);
//Crete the composition container
var container = new CompositionContainer(aggregateCatalog);
// Composable parts are created here i.e. the Import and Export components assembles here
container.ComposeParts(this);
}
catch (Exception ex)
{
throw ex;
}
}
I'm going through my plugins and executing a "Validate" method :
public List<string> Validate(string operationType)
{
List<string> res = null;
foreach (System.Lazy<IValidationRules, IPluginMetadata> plugin in ChekcsPlugins)
{
if (plugin.Metadata.DisplayName == operationType)
{
res = plugin.Value.Validate();
break;
}
}
return res;
}
I'm know how to export back a returned value once the "Validate" is done but what i need is to return values at run time back during the method execution.
Is it possible?
I use only Microsoft Azure Storage and no other Azure products/services. I upload files to my storage blob via ftp type client (GoodSync), and I need to change the content type of all the files based on their file extension after they are already in the Blob. I have looked around and have not found out how to do this without having one of their VPS with PowerShell. What are my options and how do I accomplish this? I really need step by step here.
I recently had the same issue so I created a simple utility class in order to "fix" content type based on file's extension. You can read details here
What you need to do is parse each file in your Azure Storage Containers and update ContentType based on a dictionary that defines which MIME type is appropriate for each file extension.
// Connect to your storage account
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
// Load Container with the specified name
private CloudBlobContainer GetCloudBlobContainer(string name)
{
CloudBlobClient cloudBlobClient = _storageAccount.CreateCloudBlobClient();
return cloudBlobClient.GetContainerReference(name.ToLowerInvariant());
}
// Parse all files in your container and apply proper ContentType
private void ResetContainer(CloudBlobContainer container)
{
if (!container.Exists()) return;
Trace.WriteLine($"Ready to parse {container.Name} container");
Trace.WriteLine("------------------------------------------------");
var blobs = container.ListBlobs().ToList();
var total = blobs.Count;
var counter = 1;
foreach (var blob in blobs)
{
if (blob is CloudBlobDirectory) continue;
var cloudBlob = (CloudBlob)blob;
var extension = Path.GetExtension(cloudBlob.Uri.AbsoluteUri);
string contentType;
_contentTypes.TryGetValue(extension, out contentType);
if (string.IsNullOrEmpty(contentType)) continue;
Trace.Write($"{counter++} of {total} : {cloudBlob.Name}");
if (cloudBlob.Properties.ContentType == contentType)
{
Trace.WriteLine($" ({cloudBlob.Properties.ContentType}) (skipped)");
continue;
}
cloudBlob.Properties.ContentType = contentType;
cloudBlob.SetProperties();
Trace.WriteLine($" ({cloudBlob.Properties.ContentType}) (reset)");
}
}
_contentTypes is a dictionary that contains the appropriate MIME type for each file extension:
private readonly Dictionary _contentTypes = new Dictionary()
{
{".jpeg", "image/jpeg"},
{".jpg", "image/jpeg" }
};
Full list of content types and source code can be found here.
Here you are a refreshed version for latest Azure.Storage.Blobs SDK. I'm using .Net 5 and console app.
using Azure.Storage.Blobs.Models;
using System;
using System.Collections.Generic;
using System.IO;
var contentTypes = new Dictionary<string, string>()
{
{".woff", "font/woff"},
{".woff2", "font/woff2" }
};
var cloudBlobClient = new BlobServiceClient("connectionstring");
var cloudBlobContainerClient = cloudBlobClient.GetBlobContainerClient("fonts");
await cloudBlobContainerClient.CreateIfNotExistsAsync();
var blobs = cloudBlobContainerClient.GetBlobsAsync();
await foreach (var blob in blobs)
{
var extension = Path.GetExtension(blob.Name);
contentTypes.TryGetValue(extension, out var contentType);
if (string.IsNullOrEmpty(contentType)) continue;
if (blob.Properties.ContentType == contentType)
{
continue;
}
try
{
// Get the existing properties
var blobClient = cloudBlobContainerClient.GetBlobClient(blob.Name);
var properties = await blobClient.GetPropertiesAsync();
var headers = new BlobHttpHeaders
{
ContentType = contentType,
CacheControl = properties.CacheControl,
ContentDisposition = properties.ContentDisposition,
ContentEncoding = properties.ContentEncoding,
ContentHash = properties.ContentHash,
ContentLanguage = properties.ContentLanguage
};
// Set the blob's properties.
await blobClient.SetHttpHeadersAsync(headers);
}
catch (RequestFailedException e)
{
Console.WriteLine($"HTTP error code {e.Status}: {e.ErrorCode}");
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
The question is simple as stated in the title: Is there a way of having razor helpers outside of 'App_Code'?
Example ( HtmlEx.cshtml file ):
#helper Script(string fileName, UrlHelper url)
{
<script src="#url.Content("~/Scripts/" + fileName)" type="text/javascript"></script>
}
I ask this because I don't really have anything else to put in App_Code; I want to structure my project a bit different.
Thanks.
UPDATE: I don't want any other type of extensions. I am interested in only pure razor helpers as Scott is speaking about here: http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx
The question is simple as stated in the title: Is there a way of
having razor helpers outside of 'App_Code'?
No, there isn't.
Never Say Never...
Method One: (For use in a web application project)
Just add a pre-build event to copy your file into the App_Code folder.
(But since the file must probably be included in the project, you can add an empty file with the same name to the App_Code dir, and then have the build event to update it.)
(Note, that even if you put the file originally in the App_code folder you won't get intellisense until first time building, so it is anyway not a difference.)
Method Two: (for use in a class library, in which the startup project is a web application)
In a class library the App_Code folder is not anything special, so in order to be able to have the helper page global, we have to override the razor code, as it is hard coded to make global helpers only for code in the App_code folder.
Further more the razor code is designed so that for global helpers it creates a namespace based on the full path, something that you are probably not interested.
After all we remain with a problem, that there is no intellisense available, so to avoid all these problems, I have written the following code, assuming that:
Your .cshtml (or vbhtml) files are getting copied to the final projects output directory
You add a .cs (or .vb) file with the same name as the global helpers filename, and set it's build action to "compile", (this file will be autogenerated at startup to provide intellisense)
You have to register the PreApplicationStartupClass in the AssemblyInfo.cs file
You have to replace in the PreApplicationStartupCode.Start() method, to give the relative path to your global helpers page in the Bin folder, in the order of dependency (i.e. if one of the global helper files uses helpers in the other file then it should be listed after it).
In the CustomRazorCodeHost class you have to pick the correct method of PostProcessGeneratedCode() that is appropriate for the MVC version installed
Here is the code (but one will have to add the appropriate "using" statements):
[EditorBrowsable(EditorBrowsableState.Never)]
public static class PreApplicationStartCode
{
private static bool _startWasCalled;
public static void Start()
{
// Even though ASP.NET will only call each PreAppStart once, we sometimes internally call one PreAppStart from
// another PreAppStart to ensure that things get initialized in the right order. ASP.NET does not guarantee the
// order so we have to guard against multiple calls.
// All Start calls are made on same thread, so no lock needed here.
if (_startWasCalled)
{
return;
}
_startWasCalled = true;
//Add here the the global helpers based on dependency
//also note that each global helper should have a .cs file in the project with the same name
CustomRazorHelperBuildProvider bp = new CustomRazorHelperBuildProvider();
bp.VirtualPath = "~/Bin/path/to/helpers/file/Helpers.cshtml";
bp.GenerateCodeAndCompile();
bp = new CustomRazorHelperBuildProvider();
bp.VirtualPath = "~/Bin/path/to/helpers/file/DepndentHelpers.cshtml";
bp.GenerateCodeAndCompile();
}
}
public class CustomRazorHelperBuildProvider :RazorBuildProvider
{
static List<string> GeneratedAssemblyReferences = new List<string>();
public new string VirtualPath { get; set; }
protected override System.Web.WebPages.Razor.WebPageRazorHost CreateHost()
{
return new CustomCodeRazorHost(VirtualPath);
}
private WebPageRazorHost _host;
internal WebPageRazorHost Host
{
get
{
if (_host == null)
{
_host = CreateHost();
}
return _host;
}
}
private CodeCompileUnit _generatedCode = null;
internal CodeCompileUnit GeneratedCode
{
get
{
if (_generatedCode == null)
{
EnsureGeneratedCode();
}
return _generatedCode;
}
}
private CodeDomProvider _provider = null;
internal CodeDomProvider Provider
{
get
{
if(_provider == null)
{
_provider = GetProvider();
}
return _provider;
}
}
private void EnsureGeneratedCode()
{
RazorTemplateEngine engine = new RazorTemplateEngine(Host);
GeneratorResults results = null;
using (TextReader reader = OpenReader(VirtualPath))
{
results = engine.GenerateCode(reader, className: null, rootNamespace: null, sourceFileName: Host.PhysicalPath);
}
if (!results.Success)
{
RazorError error = results.ParserErrors.Last();
throw new HttpParseException(error.Message + Environment.NewLine, null, VirtualPath, null, error.Location.LineIndex + 1);
}
_generatedCode = results.GeneratedCode;
}
private CodeDomProvider GetProvider()
{
CompilerType compilerType = GetDefaultCompilerTypeForLanguage(Host.CodeLanguage.LanguageName);
CodeDomProvider provider = CreateCodeDomProviderWithPropertyOptions(compilerType.CodeDomProviderType);
return provider;
}
/// <summary>
/// Generates the c# (or vb.net) code, for the intellisense to work
/// </summary>
public void GenerateCode()
{
//Remember that if there is a razor error, then the next time the project will not compile at all, because the generated .cs file will also have the error!
//The solution is to add a pre-build event to truncate the file, but not remove it!, also note that the pre-build event will not work in time if the .cs file is open in the VS editor!
string filePath = VirtualPath.Replace("/", "\\").Replace("~\\Bin", "").Replace("\\Debug", "").Replace("\\Release", "");
filePath = filePath.Remove(filePath.Length - 4);
//filePath = filePath.Insert(filePath.LastIndexOf("\\"), "\\HelperAutoGeneratedCode");
Assembly curAssem = Assembly.GetExecutingAssembly();
filePath = HttpRuntime.AppDomainAppPath + "\\..\\" + curAssem.GetName().Name + filePath;
using (FileStream fs = new FileStream(filePath, FileMode.Truncate))
{
using (StreamWriter sw = new StreamWriter(fs))
{
Provider.GenerateCodeFromCompileUnit(GeneratedCode, sw, null);
sw.Flush();
sw.Close();
}
fs.Close();
}
//We need to replace the type of the helpers from "HelperResult" to object, otherwise the intellisense will complain that "it can't convert from HelperResult to object"
string text = File.ReadAllText(filePath);
text = text.Replace("public static System.Web.WebPages.HelperResult ", "public static object ");
File.WriteAllText(filePath, text);
}
public void GenerateCodeAndCompile()
{
GenerateCode();
Compile();
}
/// <summary>
/// Compiles the helper pages for use at runtime
/// </summary>
/// <returns>Compiler Result</returns>
public CompilerResults Compile()
{
Assembly assem = Assembly.GetExecutingAssembly();
AssemblyName[] references = assem.GetReferencedAssemblies();
List<string> referenceNames = references.Select(r => Assembly.ReflectionOnlyLoad(r.FullName).Location).ToList();
referenceNames.Add(assem.Location);
//Add here references that are not included in the project, but are needed for the generated assembly, you can see this through the results.Errors
referenceNames.Add((typeof(WebMatrix.Data.ConnectionEventArgs).Assembly.Location));
referenceNames.Add((typeof(WebMatrix.WebData.SimpleRoleProvider).Assembly.Location));
if (GeneratedAssemblyReferences != null && GeneratedAssemblyReferences.Count > 0)
{
referenceNames.AddRange(GeneratedAssemblyReferences);
}
CompilerResults results = Provider.CompileAssemblyFromDom(new CompilerParameters(referenceNames.ToArray()), new CodeCompileUnit[] { GeneratedCode });
if (results.Errors.HasErrors)
{
IEnumerator en = results.Errors.GetEnumerator();
en.MoveNext();
CompilerError error = en.Current as CompilerError;
throw new HttpParseException(error.ErrorText + Environment.NewLine, null, VirtualPath, null, error.Line);
}
Assembly assemblyRef = GetGeneratedType(results).Assembly;
GeneratedAssemblyReferences.Add(assemblyRef.Location); //So that any subsequent helper page that is dependent on it will have it as a reference
//We need to make it available for Razor, so it will work with reguler razor pages at runtime
RazorBuildProvider.CodeGenerationStarted += new EventHandler((sender, args) => (sender as RazorBuildProvider).AssemblyBuilder.AddCodeCompileUnit(this, GeneratedCode));
return results;
}
private static CodeDomProvider CreateCodeDomProviderWithPropertyOptions(Type codeDomProviderType)
{
// The following resembles the code in System.CodeDom.CompilerInfo.CreateProvider
// Make a copy to avoid modifying the original.
var originalProviderOptions = GetProviderOptions(codeDomProviderType);
IDictionary<string, string> providerOptions = null;
if (originalProviderOptions != null)
{
providerOptions = new Dictionary<string, string>(originalProviderOptions);
}
AssemblyName[] references = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (AssemblyName reference in references)
{
if (reference.Name == "mscorlib")
{
providerOptions["CompilerVersion"] = "v" + reference.Version.Major + "." + reference.Version.Minor;
break;
}
}
if (providerOptions != null && providerOptions.Count > 0)
{
ConstructorInfo ci = codeDomProviderType.GetConstructor(new Type[] { typeof(IDictionary<string, string>) });
CodeDomProvider provider = null;
if (ci != null)
{
// First, obtain the language for the given codedom provider type.
CodeDomProvider defaultProvider = (CodeDomProvider)Activator.CreateInstance(codeDomProviderType);
string extension = defaultProvider.FileExtension;
// Then, use the new createProvider API to create an instance.
provider = CodeDomProvider.CreateProvider(extension, providerOptions);
}
return provider;
}
return null;
}
internal static IDictionary<string, string> GetProviderOptions(Type codeDomProviderType)
{
// Using reflection to get the property for the time being.
// This could simply return CompilerInfo.PropertyOptions if it goes public in future.
CodeDomProvider provider = (CodeDomProvider)Activator.CreateInstance(codeDomProviderType);
string extension = provider.FileExtension;
if (CodeDomProvider.IsDefinedExtension(extension))
{
CompilerInfo ci = CodeDomProvider.GetCompilerInfo(CodeDomProvider.GetLanguageFromExtension(extension));
PropertyInfo pi = ci.GetType().GetProperty("ProviderOptions",
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
if (pi != null)
return (IDictionary<string, string>)pi.GetValue(ci, null);
return null;
}
return null;
}
}
public class CustomCodeRazorHost : WebPageRazorHost
{
internal const string ApplicationInstancePropertyName = "ApplicationInstance";
internal const string ContextPropertyName = "Context";
internal const string WebDefaultNamespace = "ASP";
private static readonly string _helperPageBaseType = typeof(HelperPage).FullName;
public CustomCodeRazorHost(string virtualPath)
: base(virtualPath)
{
DefaultBaseClass = _helperPageBaseType;
DefaultNamespace = WebDefaultNamespace;
DefaultDebugCompilation = false;
StaticHelpers = true;
}
//Version for MVC 3
public override void PostProcessGeneratedCode(CodeCompileUnit codeCompileUnit, CodeNamespace generatedNamespace, CodeTypeDeclaration generatedClass, CodeMemberMethod executeMethod)
{
// Add additional global imports
generatedNamespace.Imports.AddRange(GetGlobalImports().Select(s => new CodeNamespaceImport(s)).ToArray());
// Create ApplicationInstance property
CodeMemberProperty prop = new CodeMemberProperty()
{
Name = ApplicationInstancePropertyName,
Type = new CodeTypeReference(typeof(HttpApplication).FullName),
HasGet = true,
HasSet = false,
Attributes = MemberAttributes.Family | MemberAttributes.Final
};
prop.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeCastExpression(
new CodeTypeReference(typeof(HttpApplication).FullName),
new CodePropertyReferenceExpression(
new CodePropertyReferenceExpression(
null,
ContextPropertyName),
ApplicationInstancePropertyName))));
generatedClass.Members.Insert(0, prop);
// Yank out the execute method (ignored in Razor Web Code pages)
generatedClass.Members.Remove(executeMethod);
// Make ApplicationInstance static
CodeMemberProperty appInstanceProperty =
generatedClass.Members
.OfType<CodeMemberProperty>()
.Where(p => ApplicationInstancePropertyName
.Equals(p.Name))
.SingleOrDefault();
if (appInstanceProperty != null)
{
appInstanceProperty.Attributes |= MemberAttributes.Static;
}
}
//Version for MVC 4
public override void PostProcessGeneratedCode(CodeGeneratorContext context)
{
// Add additional global imports
context.Namespace.Imports.AddRange(GetGlobalImports().Select(s => new CodeNamespaceImport(s)).ToArray());
// Create ApplicationInstance property
CodeMemberProperty prop = new CodeMemberProperty()
{
Name = ApplicationInstancePropertyName,
Type = new CodeTypeReference(typeof(HttpApplication).FullName),
HasGet = true,
HasSet = false,
Attributes = MemberAttributes.Family | MemberAttributes.Final
};
prop.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeCastExpression(
new CodeTypeReference(typeof(HttpApplication).FullName),
new CodePropertyReferenceExpression(
new CodePropertyReferenceExpression(
null,
ContextPropertyName),
ApplicationInstancePropertyName))));
context.GeneratedClass.Members.Insert(0, prop);
// Yank out the execute method (ignored in Razor Web Code pages)
context.GeneratedClass.Members.Remove(context.TargetMethod);
// Make ApplicationInstance static
CodeMemberProperty appInstanceProperty =
context.GeneratedClass.Members
.OfType<CodeMemberProperty>()
.Where(p => ApplicationInstancePropertyName
.Equals(p.Name))
.SingleOrDefault();
if (appInstanceProperty != null)
{
appInstanceProperty.Attributes |= MemberAttributes.Static;
}
}
protected override string GetClassName(string virtualPath)
{
return ParserHelpers.SanitizeClassName(Path.GetFileNameWithoutExtension(virtualPath));
}
}
But note that if there is a syntax error in the .cshtml file, you will have problems to compile next time (as the generated .cs file will have compile errors), however visual studio apparently has problems to pinpoint the problem.
Also sometimes the compiled code from the last build (compiled from the .cs file), can sometimes conflict with the newly updated .cshtml file.
Therefore I would recommend to add a pre-build event to truncate the file
echo. > $(ProjectDir)\Path\to\.cs\file
you can go more sophisticated and do it only if the .cshtml file has been changed (and this also applies to the code I have written above).
Use the Razor Generator extension on a view with helpers inside and you'll generate the code for the view before compilation time. The generated view code is part of your project and compiles into the assembly, so you can place the view file anywhere and use the helpers anywhere, even from a unit test.
sure, you can put them anywhere in your code or project structure. in the file where you create your helper be sure to include using System.Web.Mvc.
then just normally extend the Helper class like this:
namespace System.Web.Mvc
{
static class HtmlHelperExtensions
{
public static IHtmlString MyNewHelper(this HtmlHelper helper, string someParam)
{
// do something
}
}
}