Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Debugging with C#

12 REPLIES 12
SOLVED
Reply
Message 1 of 13
StrRevitEng
615 Views, 12 Replies

Debugging with C#

Background

In my previous post I was facing a type issue that someone helped me.

Now I tried to run my script in Revit and I get an error.

I dont know if its because its inside Revit environment, bur Im used to python and pyRevit where the error message is much  more readable and clearer regarding what I need to fix.

 

This script is not exactly new, I wrote it in python (works and in use) and now I want to learn C#.

 

What Ive tried

After reading the error message my guess is that the error has something to do with .AsString() method

I tried both .AsString() and .AsStringValue() when I want to get the Parameter's value, and also made sure that the storage type is actually string.

 

StrRevitEng_0-1727857684430.png

 

My questions

1. Is this how you normally get error messages in C#?

2. What do you think about my error? please see code below.

 

Code

 

using System;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Security.Claims;

namespace UntaggedDevicesInSheet
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class Class1 : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            // variables
            UIApplication uiApp = commandData.Application;
            Document doc = uiApp.ActiveUIDocument.Document;
            View activeView = doc.ActiveView;
            var devicesDict = new Dictionary<string, Dictionary<string, List<ElementId>>>();

            // creating a combined filter out of categories of devices we want to check if they're tagged or not
            ICollection<BuiltInCategory> device_categories = [BuiltInCategory.OST_FireAlarmDevices, BuiltInCategory.OST_SecurityDevices];
            List<ElementCategoryFilter> device_category_filters = [];

            foreach (BuiltInCategory category in device_categories)
            {
                device_category_filters.Add(new ElementCategoryFilter(category));
            }
            LogicalOrFilter devices_combined_filter = new LogicalOrFilter((IList<ElementFilter>)device_category_filters);

            // creating a combined filter out of categories of device tags we want
            ICollection<BuiltInCategory> tag_categories = [BuiltInCategory.OST_FireAlarmDevices, BuiltInCategory.OST_SecurityDevices];
            List<ElementCategoryFilter> tag_category_filters = [];

            foreach (BuiltInCategory category in tag_categories)
            {
                device_category_filters.Add(new ElementCategoryFilter(category));
            }

            LogicalOrFilter tags_combined_filter = new LogicalOrFilter((IList<ElementFilter>)tag_category_filters);


            // get all viewports in sheet
            IEnumerable<Element> allViewports = new FilteredElementCollector(doc, activeView.Id).OfClass(typeof(Viewport)).WhereElementIsNotElementType().ToElements();

            foreach (Element viewPort in allViewports)
            {
                string detailNum = viewPort.get_Parameter(BuiltInParameter.VIEWPORT_DETAIL_NUMBER).AsValueString();

                // get & sort devices by category
                ICollection<Element> allDevicesInViewport = new FilteredElementCollector(doc, viewPort.Id).WherePasses(devices_combined_filter).WhereElementIsNotElementType().ToElements();
                // sort devices by category
                List<Element> fireAlarmDevices = [];
                List<Element> securityDevices = [];

                foreach (Element device in allDevicesInViewport)
                {
                    string categoryName = device.Category.Name;
                    if (categoryName == "Fire Alarm Devices")
                    {
                        fireAlarmDevices.Add(device);
                    }
                    else if (categoryName == "Security Devices")
                    {
                        securityDevices.Add(device);
                    }
                }

                // get & sort tags by category
                IEnumerable<Element> allTagElements = new FilteredElementCollector(doc, viewPort.Id).WherePasses(tags_combined_filter).WhereElementIsNotElementType().ToElements();
                IEnumerable<IndependentTag> allTags = allTagElements.Cast<IndependentTag>();
                List<IndependentTag> allFireAlarmTags = [];
                List<IndependentTag> allSecurityTags = [];
                
                foreach (IndependentTag tag in allTags)
                {
                    string catergoryName = tag.Category.Name;
                    if (catergoryName == "Fire Alarm Device Tags")
                    {
                        allFireAlarmTags.Add(tag);
                    }
                    else if (catergoryName == "Security Device Tags")
                    {
                        allSecurityTags.Add(tag);
                    }
                }

                // Get all TAGGED fire alarm + security devices tags
                List<ElementId> taggedFireDevicesIds = allFireAlarmTags.Select(tag => tag.GetTaggedLocalElement().Id).ToList();
                List<ElementId> taggedSecurityDevicesIds = allSecurityTags.Select(tag => tag.GetTaggedLocalElement().Id).ToList();

                // Get all UNTAGGED fire alarm + security devices tags
                List<ElementId> untaggedFireDevices = fireAlarmDevices.Where(fireDevice => !taggedFireDevicesIds.Contains(fireDevice.Id)).Select(fireDevice => fireDevice.Id).ToList();
                List<ElementId> untaggedSecurityDevices = securityDevices.Where(securityDevice => !taggedFireDevicesIds.Contains(securityDevice.Id)).Select(securityDevice => securityDevice.Id).ToList();

                devicesDict[detailNum] = new Dictionary<string, List<ElementId>>
                {
                    { "fire", untaggedFireDevices },
                    { "security", untaggedSecurityDevices }
                };
            }
            string finalReport = "";
            foreach (var kvp in devicesDict)
            {
                int fireLen = kvp.Value["fire"].Count;
                int securityLen = kvp.Value["security"].Count;
                if (fireLen > 0  | securityLen > 0)
                {   
                    string viewportNum = kvp.Key;
                    finalReport += $"Viewport #{viewportNum}:\n" +
                     $"{fireLen} Untagged Fire devices\n" +
                     $"{securityLen} Untagged security devices\n" +
                 new string('-', 20) + "\n";

                }
            }
            TaskDialog.Show("Viewport Information", finalReport);


            return Result.Succeeded;

        }
    }
}

 

12 REPLIES 12
Message 2 of 13
jeremy_tammik
in reply to: StrRevitEng

Weird stuff. I suggest you explore running non-Revit-API code in the C# debugger first, before moving on to your Revit add-in. You should be able to set a breakpoint in the first line of code of your Execute method, and then stop there when you launch your external command. Your error message looks strange:

    

  • System.TypeLoadException: Could not load type 'System.Span' 1'

    

Where is the type "System.Span' 1" coming from? Who is requesting such a thing?

  

Can you debug your code at all? Can you set a breakpoint in the debugger?  Can you step into your code? 

  

Once you can do those things, you will be able to see which line of code is causing the exception.

    

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 3 of 13
StrRevitEng
in reply to: jeremy_tammik

For what its worth, before This script I opened up a console app with Visual Studio and ran some C# code lines successfully.

After that I went through Autodesk's Lesson 1: The Basic Plug-in and the add-in worked just fine...

Message 4 of 13
sragan
in reply to: StrRevitEng

I can't seem to get it to compile.  I'm no C# expert, and I tend to forget how things work if I haven't used them in a while.

 

But I don't understand the use of the square brackets in lines 34 and 35, and other similar lines.  I also don't understand the use of the $ in the string starting on line 114.

 

And I can't seem to get the compiler to understand them either 😞

 

Message 5 of 13
ricaun
in reply to: sragan

The code uses some modern C#, your can enable in your project by adding this in the csproj.

<PropertyGroup>
  <LangVersion>latest</LangVersion> 
</PropertyGroup>

 

@StrRevitEngwhat version are you build the code: .NET Core or .NET Framework? And what Revit version are you using?

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 6 of 13
StrRevitEng
in reply to: ricaun

Im using Revit  2021 and my the VS project is .net 8.0 ... Im guessing now that its a nono...

 

Where am I suppose to add it? in the manifest? at which part?

Message 7 of 13
ricaun
in reply to: StrRevitEng

Revit version 2021 to 2024 is net framework 4.8, you need to update your csproj to the correct framework.

 

Inside your csproj you need to replace the TargetFramework to net48. And you could add the LangVersion config as well.

 

Something like this:

<PropertyGroup>
  <TargetFramework>net48</TargetFramework>
  <LangVersion>latest</LangVersion> 
</PropertyGroup>

 

This should fix the 'System.TypeLoadException: Could not load type 'System.Span' 1'' error.

 

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 8 of 13
StrRevitEng
in reply to: ricaun

Thanks for the quick response, but I dont see 4.8 option ☹️

 

StrRevitEng_0-1727957379583.png

 

Message 9 of 13
ricaun
in reply to: StrRevitEng

You probably need to install in your machine the 4.8 framework.

 

Inside the Visual Studio 2022 -> Tools -> Get Tools and Features...

 

ricaun_0-1727958740502.png

 

Inside Modifying -> Individual components -> .NET Framework 4.0 targeting pack

ricaun_1-1727958860100.png

 

Select and install 😀

 

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 10 of 13
StrRevitEng
in reply to: ricaun

Thanks for helping, I did what you've said but still I dont see that 4.8 option in my project, or when trying to set up a new project... I also tried resetting my PC and VS.

StrRevitEng_0-1727962172724.png

 

Message 11 of 13
ricaun
in reply to: StrRevitEng

Looks like is not possible to change .NET Core to .NET Framework using the Application properties, but you can change directly if you edit the .csproj.

 

ricaun_1-1727963110231.png

 

When creation a new project you need to select the .NET Framework version.

ricaun_2-1727963356808.png

 

Manually editing the .csproj to change TargetFramework is the only way if you want to use the same project.

In Visual Studio you can double click in the name of the project and the .csproj open when your project was created with .NET Core template, or right click and Edit Project File.

 

ricaun_3-1727963977638.png

 

Is always a good idea to make a backup before changing the .csproj file.

 

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 12 of 13
StrRevitEng
in reply to: ricaun

Thanks for your help.

My script is running and working thanks to you.

 

The weird thing is, is that when I did Autodesk's add-in tutorial - I did it with the .net 8.0, and It worked properly.

 

In my original project I even changed the C# syntax to match the 4.8 version, But what made it finally work is creating a new project with the 'Class Library' you suggested.

Message 13 of 13
longt61
in reply to: StrRevitEng

The problem is that since Revit 2025, Autodesk switching from .Net Framework to .Net Standard. I believe that you read and tried the latest tutorial so that it instructed you to use .Net Standard (.Net 8.0). Maybe it is a coincidence that you run it on the compatible version of Revit.

This time, you did the same thing and run it in Revit 2021 which still using .Net Framework. That 's why it did not work. Normally, you can specify if it is a .Net Standard or a .Net Framework when you create a new class library project. Hope this clarify things for you.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report