I am trying to get reporting in C# to work. I'm trying to embed my rdlc file as such:
var reportDataSource = new ReportDataSource("ProspectsDataSet", _allProspects);
ReportViewer.LocalReport.DataSources.Add(reportDataSource);
ReportViewer.LocalReport.ReportEmbeddedResource = "SdcDatabase.Modules.EnquiryModule.View.Reports.ProspectsReport.rdlc";
ReportViewer.ZoomMode = ZoomMode.PageWidth;
ReportViewer.RefreshReport();
The build action on the rdlc file itself is set to embedded resource and the copy to output directory set to copy always.
I have double checked and I'm certain that that is the correct namespace in the ReportEmbeddedResource string. However when I try to load the report I get this error:
I have tried switching a few things around in the path, such as replacing '.' with '/' and '\' but so far I have not been able to get anything to fix this. I have also tried using LocalPath instead of EmbeddedResource but again I come across errors.
I have searched for this issue but haven't found anything to resolve my issue thus far.
I have a reporting wrapper class that works well for my apps. I have a property to hold the name of the ".rdlc" report definition I want to run. Then, when I call my "RunReport()" method, I assign the report based on reading a stream from my application assembly resource. A short version for what you have might be
ReportViewer.LocalReport.LoadReportDefinition( GetRDLCStream( "ProspectsReport.rdlc" ));
Then, lower, I have a method
private Stream GetRDLCStream( string rptRDLC)
{
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(
"SdcDatabase.Modules.EnquiryModule.View.Reports." + rptRDLC);
return stream;
}
Obviously, I am not positive of the naming convention of your path to your project but am implying the above path. However, it should reflect (for example)
"NameOfYourApp.SubFolderWithinPath.MaybeReportsSubFolder." + actualReport.RDLC name
This way, I never have to worry about copying out a resource and hoping the paths work. I know it is embedded and where within the assembly.
Related
This is a C# .NET 4.0 application:
I'm embedding a text file as a resource and then trying to display it in a dialog box:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "MyProj.Help.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
System.Windows.Forms.MessageBox.Show(result, "MyProj", MessageBoxButtons.OK);
}
}
The solution is MyProjSolution and the executable is MyProj.exe. Help.txt is an embedded resource. However, the stream is null. I've tried MyProjSolution.Help.txt and MyProjSolution.MyProj.Help.txt but nothing seems to work.
You can check that the resources are correctly embedded by using
//From the assembly where this code lives!
this.GetType().Assembly.GetManifestResourceNames()
//or from the entry point to the application - there is a difference!
Assembly.GetExecutingAssembly().GetManifestResourceNames()
when debugging. This will list all the (fully qualified) names of all resources embedded in the assembly your code is written in.
See Assembly.GetManifestResourceNames() on MSDN.
Simply copy the relevant name, and use that instead of whatever you have defined in the variable 'resourceName'.
Notes - the resource name is case sensitive, and if you have incorrectly embedded the resource file, it will not show up in the list returned by the call to GetManifestResourceNames(). Also - make sure you are reading the resource from the correct assembly (if multiple assemblies are used) - it's all too easy to get the resources from the currently executing assembly rather than from a referenced assembly.
EDIT - .NET Core
Please see this SO post for details on how to embed using .NET Core.
Retrieving the manifest info looks to be similar - just use this.GetType().GetTypeInfo().Assembly.GetManifestResourceNames() to get the a manifest from the assembly where the code is executing.
I haven't figured out how to do the equivalent of Assembly.GetExecutingAssembly() in .NET Core yet! if anyone knows - please let me know and I will update this answer.
I had a similar issue check first that the file is included in your project , then go to properties and set the build action of that file to Embedded Resource . this worked for me .
The embedded file's "Build Action" property should be set as "Embedded Resource" to run the line, which is given below, properly:
Stream stream = assembly.GetManifestResourceStream(resourceName)
Right click on the file, click the property and then set "Build Action" property as "Embedded Resource":
Here is the cause of my null value.
http://adrianmejia.com/blog/2011/07/18/cs-getmanifestresourcestream-gotcha/
The GetManifestResourceStream method will always returns NULL if the resource ‘built action‘ property is not set to ‘embedded resource‘
After setting this property with all the needed files assembly.GetManifestResourceStream starts returning the correct stream instead of NULL.
Just a warning.
I could not access my file as an embedded resource even though I specified that it was and even though it had that Build Action property. Wasted a lot of time banging my head. I embedded a csharp code file with .txt appended to its name (xxx.cs.txt). For some reason the GetManifestResourceNames() and GetManifestResourceStream() methods won't see a file with .cs in its name.
I renamed it simply xxx.txt and everything was fine.
Weird.
In my case the problem was that the code looking for the resource was in a different project that the resource itself.
You can only access resources that are in the same project the code is. I thought I could put all my resources in the web page project, but I need images in the mail project too.
Hope this helps someone in the same situation I was.
I find really useful calling Assembly.GetExecutingAssembly().GetManifestResourceNames();.
I had the same problem, thanks to Jay I found it was hyphens in the directory name.
ProjectName.ResourceFolder.Sub-Directory becomes ProjectName.ResourceFolder.Sub_Directory when you reference the resource stream.
A simple and streamlined solution is to have this base class:
public class EmbededResourceReader
{
protected string LoadString(string fileName)
{
return LoadString(fileName, Encoding.UTF8);
}
protected string LoadString(string fileName, Encoding encoding)
{
var assembly = this.GetType().Assembly;
var resourceStream = assembly.GetManifestResourceStream($"{this.GetType().Namespace}.{fileName}");
using (var reader = new StreamReader(resourceStream, encoding))
{
return reader.ReadToEnd();
}
}
}
Then, when you add a resource, you create a reader C# class in the same folder:
where the reader class MyResource.cs is very simple:
public class MyResource : EmbededResourceReader
{
public string LoadString() => LoadString($"{nameof(MyResource)}.txt");
}
So, each resource will have a "shadow" class that knows how to read it properly.
This is how you read the resource in your code:
var text = new MyResource().LoadString();
And as other answers suggested, do not forget to set "Embedded Resource" in the Build Action property of the resource file.
The advantage of this uniform solution is
less hassle with finding correct full name of the resource, especially when placed in nested folders
in case when folder is renamed OR Default Namespace in project settings is changed, the code will NOT break
In case it helps anyone else, Make sure Assembly.GetExecutingAssembly() line is called from same assembly which has embedded resources.
First Unload the project and click on edit the project file.
Inside the project file make sure that the item you are fetching from the assembly is included inside <EmbeddedResource> tag.
Eg:
<ItemGroup>
<EmbeddedResource Include="Template\ForExampleFile.html" />
</ItemGroup>
The files I added into the project were just in Content tag but not in the EmbeddedResource as shown below by default. Hence the stream was returning null.
<ItemGroup>
<Content Include="Template\ForExampleFile.html" />
</ItemGroup>
You need to unload your solution.Then edit project.Afterfind your folder and change like this:
<EmbeddedResource Include="yourpath" />
Although OP got GetManifestResourceStream returning NULL from resources in the same Assembly, some Answers suggested that when Resources are in another Project or Assembly they cannot be retrieved, and are a fair cause of GetManifestResourceStream returning NULL.
This is not true, at least since 2011; as I pointed in some comments elsewhere, Assembly.LoadFrom() or typeof do the trick and as a result you can access resources that are in another project.
I have a moderately complex example here to illustrate; this is my test setup:
Path to another project:
Captured here:
var sharedXMLResource =
"D:\\My Documents\\Consultório Impressos\\DB Pacientes\\Teste\\TestesVariados\\WinFormFramework\\Read_Embedded_XML_File_CS\\bin\\Debug\\Read_Embedded_XML_File_CS.exe";
And on Form1.cs from WinFormFramework I specify with
Namespace.Folder.Resource
like that:
StreamReader reader =
new StreamReader(Assembly.LoadFrom(sharedXMLResource).GetManifestResourceStream("Read_Embedded_XML_File_CS.SharedResources.ContactList.xml") ?? throw new InvalidOperationException());
And the result displayed at textbox:
I spent several hours to get it right; for that, I had to use a lot these at Immediate Window:
Environment.CurrentDirectory
AppDomain.CurrentDomain.BaseDirectory
System.Reflection.Assembly.GetExecutingAssembly().Location
System.Reflection.Assembly.GetAssembly(typeof(WinFormFramework.Program)).Location
Hope it helps someone
I know this is an old question, however, I stumbled through this and with the help of #Jay answer I was able to get this working.
I had to use the full filename to get this to work.
using var stream = assembly.GetManifestResourceStream("Project.Folder.appsettings.json");
You probably need to specify the path to your txt file in the GetManifestResourceStream parameter, or you could try sticking the txt file in the same directory as your executable. Hope that helps!
I want to load a xml document Swedish.xml which exists in my solution. How can i give path for that file in Xamarin.android
I am using following code:
var text = File.ReadAllText("Languages/Swedish.txt");
Console.WriteLine("text: "+text);
But i am getting Exception message:
Could not find a part of the path "//Languages/swedish.txt".
I even tried following lines:
var text = File.ReadAllText("./Languages/Swedish.txt");
var text = File.ReadAllText("./MyProject/Languages/Swedish.txt");
var text = File.ReadAllText("MyProject/Languages/Swedish.txt");
But none of them worked. Same exception message is appearing. Build Action is also set as Content. Whats wrong with the path? Thanks in advance.
Just try with this
string startupPath = Path.Combine(Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.Parent.FullName, "Languages", "Swedish.txt");
var text = File.ReadAllText(startupPath);
Try...
Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)+"/Languages/Swedish.txt"
If you mark a file as Content Type, it will be included in the app bundle with the path that you are using within your project file. You can inspect the IPA file (it's just a renamed zip) that is created to verify that this is happening.
var text = File.ReadAllText("Languages/Swedish.txt");
should work. The file path is relative to the root of your application. You need to be sure that you are using the exact same casing in your code that the actual file uses. In the simulator the casing will not matter, but on the device the file system is case sensitive, and mismatched casing will break the app.
I've looked into this before and never found any solution to access files in this way. All roads seem to indicate building them as "content" is a dead end. You can however place them in your "Assets" folder and use them this way. To do so switch the "Content" to "AndroidAsset".
After you have done this you can now access the file within your app by calling it via
var filename = "Sweedish.txt";
string data;
using
(var sr = new StreamReader(Context.Assets.Open(code)))
data = sr.ReadToEnd();
....
Basically, I'm building a website that allows user to upload file.
From the front end (JavaScript), the user will browse a file, I can get the site to send POST data (the parameter "UploadInput" and it's value, which the value is the file)
In the backend (C#), I want to make a copy of the file and save it in a specific path.
Below is the way I did it.
var files = Request.Files;
file[0].SaveAs("\temp\\" + file[0].FileName);
The problem I ran into is that I got the error message saying index out of range. I tried Response.Write(files.Count) and it gives me 0 instead of 1.
I'm wondering where I did wrong and how to fix it, or if there's a better way of doing it.
Thanks!
Edit:
I am using HttpFox to debug. From HttpFox, I can see that under POST data, parameter is "UploadInput" and the value is "test.txt"
Edit 2:
So I tried the way Marc provides, and I have a different problem.
I am able to create a new file, however, the content is not copied over. I tried opening the new created file in notepad and all it says is "UploadInput = test.txt"
If they simply posted the file as the body content, then there will be zero "files" involved here, so file[0] will fail. Instead, you need to look at the input-stream, and simply read from that stream. For example:
using(var file = File.Create(somePath)) {
Request.InputStream.CopyTo(file);
}
I keep getting the error "Stream was not writable" whenever I try to execute the following code. I understand that there's still a reference to the stream in memory, but I don't know how to solve the problem. The two blocks of code are called in sequential order. I think the second one might be a function call or two deeper in the call stack, but I don't think this should matter, since I have "using" statements in the first block that should clean up the streams automatically. I'm sure this is a common task in C#, I just have no idea how to do it...
string s = "";
using (Stream manifestResourceStream =
Assembly.GetExecutingAssembly().GetManifestResourceStream("Datafile.txt"))
{
using (StreamReader sr = new StreamReader(manifestResourceStream))
{
s = sr.ReadToEnd();
}
}
...
string s2 = "some text";
using (Stream manifestResourceStream =
Assembly.GetExecutingAssembly().GetManifestResourceStream("Datafile.txt"))
{
using (StreamWriter sw = new StreamWriter(manifestResourceStream))
{
sw.Write(s2);
}
}
Any help will be very much appreciated. Thanks!
Andrew
Embedded resources are compiled into your assembly, you can't edit them.
As stated above, embedded resources are read only. My recommendation, should this be applicable, (say for example your embedded resource was a database file, XML, CSV etc.) would be to extract a blank resource to the same location as the program, and read/write to the extracted resource.
Example Pseudo Code:
if(!Exists(new PhysicalResource())) //Check to see if a physical resource exists.
{
PhysicalResource.Create(); //Extract embedded resource to disk.
}
PhysicalResource pr = new PhysicalResource(); //Create physical resource instance.
pr.Read(); //Read from physical resource.
pr.Write(); //Write to physical resource.
Hope this helps.
Additional:
Your embedded resource may be entirely blank, contain data structure and / or default values.
A bit late, but for descendants=)
About embedded .txt:
Yep, on runtime you couldnt edit embedded because its embedded. You could play a bit with disassembler, but only with outter assemblies, which you gonna load in current context.
There is a hack if you wanna to write to a resource some actual information, before programm starts, and to not keep the data in a separate file.
I used to worked a bit with winCE and compact .Net, where you couldnt allow to store strings at runtime with ResourceManager. I needed some dynamic information, in order to catch dllNotFoundException before it actually throws on start.
So I made embedded txt file, which I filled at the pre-build event.
like this:
cd $(ProjectDir)
dir ..\bin\Debug /a-d /b> assemblylist.txt
here i get files in debug folder
and the reading:
using (var f = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Market_invent.assemblylist.txt")))
{
str = f.ReadToEnd();
}
So you could proceed all your actions in pre-build event run some exes.
Enjoy! Its very usefull to store some important information and helps avoid redundant actions.
I've created a custom configuration section using XSD. In order to parse the config file that follows this new schema, I load the resource (my .xsd file) with this:
public partial class MonitoringConfiguration
{
public const string ConfigXsd = "MonitoringAPI.Configuration.MonitoringConfiguration.xsd";
public const string ConfigSchema = "urn:MonitoringConfiguration-1.0";
private static XmlSchemaSet xmlSchemaSet;
static MonitoringConfiguration()
{
xmlSchemaSet = new XmlSchemaSet();
Stream xsdStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ConfigXsd);
XmlReader schemaReader = XmlReader.Create(xsdStream);
xmlSchemaSet.Add(ConfigSchema, schemaReader);
}
}
By the way my resource is: MonitoringConfiguration.xsd. And the namespace of the other partial class (that represents the code behind of the .xsd file) is MonitoringAPI.Configuration.
The problem is situated here:
Stream xsdStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ConfigXsd);
The xsdStream is null, so I guess the resource can't be found! But why?
Thank you
The name of the resource is always:
<Base namespace>.<RelativePathInProject>.<FileName>
So if your resource is located in "Resources/Xsd/", and your default project namespace is "MonitoringAPI.Configuration", the resource name is:
"MonitoringAPI.Configuration.Resources.Xsd.MonitoringConfiguration.xsd"
Also make sure the build action for your resource is set to "Embedded Resource"
Easy and correct way to get the actual name of your embedded resource:
string[] resourceNames =
Assembly.GetExecutingAssembly().GetManifestResourceNames();
Then simply check resourceNames array, and you will know for sure what to pass to GetManifestResourceStream method.
In my case,
When you try to access the file via GetManifestResourceStream(). You will get an error due to invalid path of the file, and stream will be null.
Solution:
Right click on the file which you have added in to solution and Click on Properties.
Select the Build Action as Embedded Resource. (Instead of Content - by default)
By default, visual studio does not embed xsd file therefore you must ensure "Build Action" property of xsd file is set to "Embedded Resource" to make it works
just add your resources under form1.resx -->add existing items
double click on the resources you added under Resources folder.go to properties and select "Embedded Resources" instead of none.
Then
try debugging the line:
string[] resourceNames=Assembly.GetExecutingAssembly().GetManifestResourceNames();
check the resources you added are in the array. then copy the resource name exactly from this array and try putting the name on your code..it works fine!!
You can get the Resource Stream by passing the Resource Names which is as follows below...
Get the resource name e.g..
Assembly objAssembly = Assembly.GetExecutingAssembly();
string[] strResourceNames = objAssembly.GetManifestResourceNames();
Pass the Resource Names to ...
Stream strm = objAssembly.GetManifestResourceStream(strResourceNames);
Now you have Stream you can do whatever you want...
In my case, it was something completely different:
My UWP App compiled correctly in Debug and Release configuration but GetManifestResourceStream returned Null only Release configuration.
The issue was, that in the UWP Build Configuration file (and only there) the setting "Compile with .NET Native tool chain" was enabled. After disabling, GetManifestResourceStream worked as expected.
I had an issue where I was embedding a whole heap of .xsd files in many different assemblies; everything was working (GetManifestResourceNames was returning the files I'd expect to see) except for one. The one which wasn't was called:
Something.LA.xsd
I wasn't dealing with specific cultures and the .LA bit at the end of the filename was being picked up by the compiler as this file being for the LA culture - the filename in the manifest was going in as Something.xsd (under culture LA) - hence me not being able to find it (it ended up in a satellite assembly). I dodged the issue by renaming the file - presumably it is possible to explicitly state the culture of a given embedded resource.
Actually, a quick google reveals:
How can I prevent embedded resource file culture being set based on its filename
According to this answer, you've got to do hacky things - so perhaps renaming the file wasn't so bad after all :)