OWIN WEB API self host resolve path to folder - asp.net-web-api

Form inside an ApiController. I need to read content of a file embedded inside the project. But I can't resolve the correct path
[HttpPost]
public HttpResponseMessage DoSomething()
{
String content = System.IO.File.ReadAllText(#"~\SomeFolder\file.txt");
}
Doing like this the resolved path point to:
C:...\bin\Debug\~\SomeFolder\file.txt
instead of
C:...\SomeFolder\file.txt
Does anyone have any idea how to solve this under OWIN Self Host?

In general, it does not make sense to try to access a file inside a project. All the files necessary for deployment (dlls, assets, txts,...) should be copied to a separated folder so that when we need to deploy, we just need to copy that folder.
You should set the file as Copy To Output and try:
String content = System.IO.File.ReadAllText(#"SomeFolder\file.txt");
which is resolved to
C:...\bin\Debug\SomeFolder\file.txt
To make the code work with OWIN, you could take a look at this answer How do you resolve a virtual path to a file under an OWIN host?. It suggests using HostingEnvironment.MapPath and falling back to manipulating file paths manually in self host scenario.

Related

attaching unit test data to unit tests in visual studio

I heavily make use of unit tests for my developer needs (POCs, unit tests, etc). For one particular test method there was a line that went...
var file = #"D:\data\file.eml";
So I am referencing some file on my file system.
Now in a team when other people are trying to run my "personal" tests (POCs or whatever) they don't have a reference to that file in that path...hence the tests fails. How we'd have to normally make this work is to provide the test data, and allow the user to modify the test code so that it runs on his computer.
Any visual studio way to manage this particular problem?
Whats the benefit in this? Well, people can review the test data (email in my case) as well as the method I wrote for testing, and can raise defects in TFS (the source control system) relating to it if need be.
One way I often handle data files for unit test projects are to set the data files as Resources. (* Note that this link is for vs2010 but I have used this approach through vs2015RC).
In the project with the data file: Project -> Properties -> Resources and choose to add a resource file if you the project doesn't already have one. Select Files in the resource pane and click Add Resource or just drag and drop your data files onto the resource manager. By default resources are marked internal, so to access the resources from another project you have several ways:
In the assembly with the data files, add the following to your AssemblyInfo.cs file and this will allow only specified assemblies to access the internal resources
[assembly: InternalsVisibleTo("NameSpace.Of.Other.Assembly.To.Access.Resources")]
Create a simple provider class to abstract away the entire Resource mechanism, such as:
public static class DataProvider
{
public static string GetDataFile(int dataScenarioId)
{
return Properties.Resources.ResourceManager.GetString(
string.Format("resource_file_name_{0}", id));
}
}
Change the resource management to public (not an approach I have used)You can then access the data file (now a resource) from a unit test such as:
[TestCase(1)]
public void X_Does_Y(int id)
{
//Arrange
var dataAsAString = Assembly_With_DataFile.DataProvider.GetScenario(id);
//Act
var result = classUnderTest.X(dataAsAString);
//Assert
Assert.NotNull(result);
}
Note that using data files as resources, the ResourceManager handles the file I/O and returns strings of the file contents.
Update: The test method in the example above is from an NUnit project and is not meant to imply process, but a mechanism by which a data file can be accessed from another project.
What you'd normally do is add the file to your project and check it into TFS. Then make sure the item's settings are:
Build action: Content
Copy to output: If newer
Then put an attribute on your Test method or Test class:
[DeploymentItem("file.eml")]
You can optionally specify an output dircetory:
[DeploymentItem("file.eml", "Directory to place the item")]
If you put the files in subdirectories of your test project, then adjust the attribute accordingly:
[DeploymentItem(#"testdata\file.eml")]
The file will be copied to the working directory of your test project and that makes it easy to access from your test code. Either load the file directly, or pass the path to any method that needs it.
If you tests expect the files in a specific location you can use a simple System.IO.File.Copy() or System.IO.File.Move() to put the item in the place you need it to be.
The process is explained here on MSDN.
I suppose the most straight forward way is to simply add whatever to the project, and set the correct value for Copy To Output Directory. In other words, say your data is in a text file.
Add text file to your test project
Right-click to access properties window
Set copy to output directory field as Always or Copy if newer.
Now if you build the test project, the file gets copied to your output directly. This enables to write unit test code of the fashion:
var dataFile = File.OpenRead("data.txt");

How can I replace config file database links in one place in source code? (asp.net/razor)

I have an ASP.NET/Razor 3 web application which uses a SQL Server database via MS EntityFramework.
If/when I want to change the database connection string, for example to change the password or point to a different database (e.g. test vs. live), the string needs to replaced in about seven places in three different XML config files in the project (app.config, web.config, and app.release.config), which is an error-prone pain.
Worse, the default web server behavior on unhandled exceptions can include displaying sections of the config files to web users, which has in fact resulted in the web server displaying the lines that show the database path and password over the web. Not good.
For both reasons, and because this is not a product for which anyone would ever just edit the config file on the server (any change is pretty much, and may as well be, a build operation), I would much prefer to have the database connection information compiled into the web application and loaded from code rather than a config file, and to be able to do this such that when I want to change the database information, I can do it in one place instead of seven.
How would I achieve this?
The database connection string(s) can be set up centrally in 1 place, in the Global.asax.cs file, as part of the Application State, and then referenced from anywhere else in the project.
Step-1: Define the connection string(s) as static variables in Global.asax.cs:
namespace TestProject
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static string ConnectionString1;
public static string ConnectionString2;
protected void Application_Start()
{
#region Build application state for the app-specific items needed by us
ConnectionString1 = "Server=yourserver;Database=yourdb;etc etc";
ConnectionString2 = "Server=yourserver;Database=yourdb;etc etc";
#endregion
#region Code auto-generated and needed by system - do not change
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
#endregion
}
}
}
Step-2: Use the strings from anywhere else in the project:
string cnxStr1 = TestProject.MvcApplication.ConnectionString1;
string cnxStr2 = TestProject.MvcApplication.ConnectionString2;
(Please note that by default, the strings would be accessible only from within the same project. You will need to add references to the project if you need to use the strings from any other project within the same solution.)
The answer above by Krishna is pretty good. For me I would personally prefer to have them as static string in a static class and use it where ever is needed.
If you don't want to put the connection strings in the global file, you can:
Create a separate .config file for connection strings. e.g.
connectionStrings.config.
Create a hard-link to this file or the
folder containing this file that's in the same directory as your
other application.config and web.config files.
Set the configSource property on the connectionStrings element in each app.config or
web.config.
From then on, you only have one place to manage your connection strings that are common between apps.
The reason for the hard link is that configSource must reference a file in the same folder or sub-folder of the folder containing the application config.
Note that changing the connection strings will recycle all your web application pools that use them. For console, desktop, and service apps, you will have to restart for changes to take effect.
For the second problem you describe, you could have a separate connectionStrings.config file for each environment: development, test, production. Using config transforms or some other process, you only have to update the configSource property in each connectionString element to switch environments.

Can you use a URL to embed an image inline in MVCMailer

In looking at the MVCMailer step by step, I see that you can embed images inline using cid in the HTML.
https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide
I see the code that talks about embedding:
#Html.InlineImage("logo", "Company Logo")
var resources = new Dictionary<string, string>();
resources["logo"] = logoPath;
PopulateBody(mailMessage, "WelcomeMessage", resources);
My question is rather than use a path within the site like:
resources["logo"] = Server.MapPath("~/Content/images/logo.png");
Can I somehow get at images I have in the Azure Cloud or S3 Cloud where I have plenty of space?
Please let me know if there is a way to get the image from some other source than the server the MVC mailer is running on.
Thanks,
Victor
In Server.MapPath(my_path), my_path, specifies the relative or virtual path to map to a physical directory. Server.MapPath is related with local FileSystemObject so in that case it will look for the file (you pass as parameter) in a location within local web server. More info is described here:
http://msdn.microsoft.com/en-us/library/ms524632(v=VS.90).aspx
So if you image is located at http://azure_storage_name.blob.core.windows.net/your_public_container/image_name.jpg, the passing it to Server.MapPath() will not work as this is not a location in local file system. I tried and found that it will not accept and I also try to tweak a few way but no success. IF you can change the code behind and which can access the resources from a URL then it will work otherwise not.

What is the best way to let access to physical files in ASP.NET MVC3

I did not find which is the best following to serve physical files to the users in a MVC3 app.
For example if I want to put my site in search engines, they ask me to place an xml file in the site root.
This file can not be accessed because I think the routing does not "catch" the url...
Thanks¡¡
You should be able to ignore route:
routes.IgnoreRoute("/filename.xml");
Or:
routes.IgnoreRoute("filename.xml");
And that should be done in Global.asax file and RegisterRoutes() function
did you try opening the file through your web browser?
if you tried and it didn't open then you can do the following
in global.asax
write the following
C#
routes.IgnoreRoute("{xml}", new { xml = #"(.)?abc.xml" }); where abc is the file name or you can but * instead of abc to ignore all xml files
You can just set the permissions on the file system with a chmod (700) or equivalent. Usually this is where the protections come in.

using an image embedded in a directory of a dll

I have a .NET 4.0 class library with a directory called Resources, with an image called Logo.bmp inside it set to be compiled as an embedded resource.
In my main application I add the dll reference and set a Uri to pack://application:,,,/ResourceImages;component/Resources/logo.bmp and then I try to get the resource stream to that resource (using Application.GetResourceStream(myUri)) but it can't find the resource specified.
If however I put the image in the root directory of my dll and take out the Resources/ it can find and return the resource stream without issue.
Any suggestions?
to anyone else who might be having this particular issue, make sure that you build the string to pass into the new uri BEFORE you make the new call, not during. I changed it so that the pack: location string is all created ahead of time and now it works

Resources