Cleanest way to package content files in .nuget package

Viewed 1988

So I have set up which looks something like following:

Source.sln have three project A.csproj, B.csproj and utils.csproj. Both A and B use utils.csproj but I have converted utils.csproj to a nuget package so now A and B both consume utils nuget package instead of a project reference.

next thing I do is make nuget packakage from both bot A and B. So now I have three nuget packages

1.A.Nuget(uses utils.nuget) 2.B.nuget(uses utils.nuget) 3. Utils.nuget

Now, I have another consumer.csproj which uses all three as nuget references.

The problem here is that Both A.csproj and B.csproj had inputA.json and inputB.json files which are required at the runtime. They do not change at all so it is better that they are packaged with nuget package

My question is that what is the cleanest way to paclage them? I thought of couple of options but am not satisfied by either of them:

  1. pack them in utils.nuget's /content folder by specifying that in .csproj file. But the problem here is that the code reading them from nuget needs to reference thse files from ../contents/inputA.json which is not the case in Development environment. They simply reside in A.csproj/ folder and can be referenced as "input.json". So the same code which works on Visual studio(referencing this file as input.json) would break when consumer.csproj references A.nuget and utils.nuget

    1. have Consumer supply all these files. This could be an option but I want to avoid it if possible.

    2. Somehow figure out a way to copy this files into /lib folder of utils.nuget instead of /contents. I am currently trying to achieve this using .nuspec file. but not sure if this is the cleanest solution

Can I do something better about this situation?

2 Answers

In my opinion, the best solution would be to make the file an embedded resource. Since you said that the files don't change, there's no benefit to having them as a file on disk. But, if you're going to embed them, you might as well convert it to code so your code doesn't have to waste CPU cycles parsing and deserialising the json file.

If some of your package comsumers will occasionally want to change the contents, then I think making your package have an extensible API would be better than having a configuration file. I don't know if you've worked at all with ASP.NET Core, but I think their configuration is brilliant. All configuration is though code, using callbacks. For example:

app.UseWhateverMiddleware(options => {
  // options contains default values, my app can change the values I care about here
})

This solves so many problems. If your package overwrites project's content files, then your package's consumers will lose their customisations. If your package doesn't overwrite content files, then you don't have a good way to update defaults or add new options to projects already using your package. Depending on who your customers are, they might not be happy about being forced to configure your library though a file that must be deployed with their app. Particularly for web apps, some people like config files, some people store config in a database, or environment variables, all config in a single file, different config files for different libraries, or different config files for different areas/features of the app.

By using the ASP.NET Core Options Pattern, it allows projects to be configured how the project wants, not how the package wants.

The cleanest(which is inherently not a very clean) to pack files and read it from everywhere is to basically make sure that these files end up in consumer project's /bin folder. The way to do this is using .nuspec file.

If files are mapped inside .nuspec metadata as .nuspec file:

<metadata> // This path automatically resolves to /contentfiles/any/any <contentFiles> <files include="Yourfilename" buildAction="none" copyToOutput="true"/> </contentFiles> </metadata>

<files> <file src="../path/to/your/file" target="contentFiles\any\any" />
</files>

because of the option CopyToOutput = "true" These files would directly be copied to /bin folder of referencing project.

Related