Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot run project after it is built, error with finding the file An exception of type 'System.IO.DirectoryNotFoundException' occurred in System.Xml.dll but was not handled in user code Additional information: Could not find file "IO.Swagger.xml" #2914

Closed
doughjoe77 opened this issue May 19, 2016 · 7 comments · Fixed by #3306

Comments

@doughjoe77
Copy link

Description

I've created a .NET MVC Project using Swagger Editor using "PetStore on Heroku" example. The zip file downloads fine and after I extract that I'm able to build the project. When I try to run it I get the following error:

An exception of type 'System.IO.DirectoryNotFoundException' occurred in System.Xml.dll but was not handled in user code

Additional information: Could not find a part of the path 'C:\Users[user]\Desktop\pet-store-api\src\artifacts\Debug\dnx451\IO.Swagger.xml'.

Swagger-codegen version

I'm using the public editor: http://editor.swagger.io/

Swagger declaration file content or url
Command line used for generation
Steps to reproduce

This is in Visual Studio 2015 Update 2

  1. open up the editor on http://editor.swagger.io/
  2. choose the "PetStore on Heroku" example
  3. download the AspNet5 project
  4. extract the zip to a folder
  5. open the project.json with Visual Studio 2015
  6. run the project
Related issues
Suggest a Fix

Seems like the IO.Swagger.xml is not being generated, pre-AspNet5 there was a property on the project that would create that file, seems like it's not being generated now, if it was generated that should fix the issue.

@jimschubert
Copy link
Contributor

I'll have to check this out. I've downloaded the server generator code from editor.swagger.io in the same way mentioned above and run it successfully, but it's been a couple months. I don't know what's changed in that time. What version of .NET Core are you running? Is Visual Studio not using RC1-final which is required by the project?

@doughjoe77
Copy link
Author

By default it looks like its using "1.0.l-rc1-final". I figured out what is happening and was able to correct it to a degree, by default line 69 in the Startup.cs has the xmlComments variable set to "C:\Users\Desktop\Project\aspnet5-server\src\artifacts\Debug\dnx451\IO.Swagger.xml", which doesn't exist. I found the xml I thought it would need in the artifact directory "C:\Users\Desktop\Project\aspnet5-server\src\artifacts\bin\Project\Debug\dnxcore50\IO.Swagger.xml". If I hard code that value in line 69 or set the xmlComments to that it works fine (service starts up without an error and shows the Swagger UI Page). Could be the update 2 of VS 2015 doesn't write out the file to the appropriate place (or it's changing as they finalize .NET Core)?

I went a bit further and fixed the code so it works, also fixed a potential bug where this would fail if you changed the project folder from Swagger.IO to something else (which is what I did), here is the code (starting at line 35):

  // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        var projectName = Path.GetFileName(Directory.GetDirectories(GetSolutionBasePath()).Last());
        // changed from IO.Swagger.xml, noticed that if you change the project name the xml fle is generated with a different name, parameter 5
        string xmlComments = string.Format(@"{0}{4}artifacts{4}{1}{4}{2}{3}{4}{5}.xml", 
               GetSolutionBasePath(),
               _appEnv.Configuration,
               _appEnv.RuntimeFramework.Identifier.ToLower(),
               _appEnv.RuntimeFramework.Version.ToString().Replace(".", string.Empty),
               Path.DirectorySeparatorChar,
               projectName);
        // using later versions of Visual Studio 2015 changes the generated location of the comments file
        if (!File.Exists(xmlComments))
        {
            xmlComments = string.Format(@"{0}\artifacts\bin\{1}\{2}\dnxcore50\{1}.xml", 
                GetSolutionBasePath(), 
                projectName, 
                _appEnv.Configuration);
            if (!File.Exists(xmlComments))
                throw new Exception(
                    string.Format("Cannot find project's generated Comments XML File ({0}), Swagger UI will fail until the file can be generated", 
                    xmlComments));
        }

I'm worried a bit about deployment, not sure if the deployed code would work with the same directory structure. Also not sure if that will be the "final" way to identify the project name. Heard through the grapevine that the project.json was being deprecated to some degree and there will be a new project file (VS generated the following file for me when I saved it: Project.xproj).

@doughjoe77
Copy link
Author

I also had to make a change to the project properties, you need to do the following:

  1. right click on the project in VS 2015, choose properties
  2. choose the build side tab "Build" and check off "Produce outputs on build"
  3. do a "Save All", should create a new *.xproj file and a *.sln file which it will ask you to save. Once you do that the code above will work.
    fix swagger io project

The "IO.Swagger.xproj" file was generated with the following XML:

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> </PropertyGroup> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> <PropertyGroup Label="Globals"> <ProjectGuid>f2e71abb-7746-4b0e-bb2f-93884e357100</ProjectGuid> <RootNamespace>IO.Swagger</RootNamespace> <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> <OutputPath Condition="'$(OutputPath)'=='' ">..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> </PropertyGroup> <PropertyGroup> <SchemaVersion>2.0</SchemaVersion> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> </PropertyGroup> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> </Project>

@jimschubert
Copy link
Contributor

jimschubert commented Jun 6, 2016

I've tested this with the same project pulled from editor.swagger.io. It seems the only piece that's missing for this to run as expected in Visual Studio 2015 is to run

dnu pack src\IO.Swagger --out src\artifacts

From the downloaded content's root after building in Visual Studio.

I didn't have issues with building the project as-is downloaded from the site (right-clicked project, did build). I also didn't have to change project properties, although it seems the properties you've changed result the same artifacts being output as the command above.

I think the bug here is actually that the server generator stub doesn't include a README listing the steps to compile or a batch file to compile directly under Windows. For reference until I add these changes, the steps are available in the shell script:

dnu restore src/IO.Swagger/
dnu build src/IO.Swagger/
dnu pack src/IO.Swagger/ --out artifacts
dnx --project src/IO.Swagger/project.json web

However, and I'm not sure why there's a difference, the third step is dnu pack src/IO.Swagger/ --out src/artifacts

One thing I notice in your screenshot is the run configuration shows IIS Express. That will fail, you need to drop that down to web to run this correctly. I don't know why VS doesn't default to that.

Thanks for posting the .xproj contents. The project.json based projects will actually be converted to .csproj after the next release candidate, so I'm going to wait until that version is out to update the generator from rc1-final and include the project file. If I remember correctly the xproj file isn't supported by Visual Studio Code or Xamarin on Mac, and the intention of the generator is to be cross platform.

  • Add Readme to aspnet5 generator
  • Add a build.bat to aspnet5 generator
  • Integrate recommended changes to ConfigureServices method (evaluate cross platform: OS X, Linux, and Windows)

@jimschubert
Copy link
Contributor

It actually looks like "the next release candidate" is 1.0 RTM. I will update everything for that after it is released later this month.

@jimschubert
Copy link
Contributor

Per https://blogs.msdn.microsoft.com/webdev/2016/06/27/announcing-asp-net-core-1-0/, the RTM release didn't contain the .csproj/.sln changes:

We are still working on the plan for csproj / msbuild. Now that .NET Core 1.0 has been released, we can devote much more time to it. We hope to have more to say soon. Watch the blog.

I'll work on any interim changes.

@jimschubert
Copy link
Contributor

jimschubert commented Jul 4, 2016

@doughjoe77

I'm working on updating the aspnet5 generator to ASP.NET Core 1.0.0-preview2. This will change a bit because IApplicationEnvironment will no longer exist.

This is what ConfigureServices will look like:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc()
        .AddJsonOptions(
            opts => { opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); });

    services.AddSwaggerGen();

    services.ConfigureSwaggerGen(options =>
    {
        options.SingleApiVersion(new Info
        {
            Version = "v1",
            Title = "IO.Swagger",
            Description = "IO.Swagger (ASP.NET 5 Web API 2.x)"
        });

        string xmlComments = $"{AppContext.BaseDirectory}\\IO.Swagger.xml";
        options.OperationFilter<XmlCommentsOperationFilter>(new XPathDocument(xmlComments));
    });
}

I didn't test this change in the previous version, but I thought I'd share here while I'm working on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants