A very frequent question from developers in the past has been about suppressing various warning and error messages in Revit.
One of the many
new Revit 2011 API features specifically
targeted at allowing an add-in to integrate very tightly with Revit and its user interface is the new Failure API, providing the ability for an add-in to react to and suppress failures as well as define its own new ones and post them.
This is the description in the What's New section of the Revit API help file RevitAPI.chm:
There are two capabilities offered by the new failure API:
This section offers a high level overview of both capabilities; more detail about the failures API is provided in the "Failure API" document in the Revit API help file.
As a part of exposing these new capabilities, all overloads accepting "PostedErrors" have been removed from the API.
If you are using the failure posting mechanism to report your problem, all you need to do is:
Normally posted failures are processed by Revit's standard failure resolution UI at the end of transaction. The user is presented information and options in the UI to deal with the failures.
However, if your operation (or set of operations) on the document requires some special treatment for certain errors (or even all possible errors), you can customize failure resolution. Custom failure resolution can be supplied:
Finally, the API offers the ability to completely replace the standard failure processing user interface using the interface IFailuresProcessor.
Failure API
Failure posting
Failure handling
The use of the new failure API is demonstrated very comprehensively by the ErrorHandling Revit SDK sample, which shows how to create a failure definition id, failure definition, failure message and how to resolve failures in failure processing steps. It suppresses a warning message for overlapping walls. For more detailed information on that sample implementation, please refer to its read-me document ReadMe_ErrorHandling.rtf.
This sample is quite extensive and demonstrates many aspects of the failure API. When looking at it, one of my colleagues came up with some questions requesting clarification of its expected behaviour:
Leo Lu, the author of the sample, responded to these questions:
Here is another example of using the failure API which is less extensive and therefore much smaller and simpler:
Harry Mattison of the Revit development team provided this small and sweet sample of using the failure API to suppress a specific warning message. It includes the RoomWarningSwallower IFailuresPreprocessor implementation used as sample code for the IFailuresPreprocessor interface in the Revit API help file.
The command creates an unbounded room and suppresses the warning that would otherwise be given saying "Room is not in a properly enclosed region".
The duration for this implementation is only for the transaction in the external command, so after the command is executed manually placed unbounded rooms do result in the warning again a usual.
However, as mentioned above, it is also possible with the new failure API to suppress warnings for the entire Revit session.
Here is the implementation of the warning swallower class implementing the IFailuresPreprocessor interface:
public class RoomWarningSwallower : IFailuresPreprocessor { public FailureProcessingResult PreprocessFailures( FailuresAccessor a ) { // inside event handler, get all warnings IList<FailureMessageAccessor> failures = a.GetFailureMessages(); foreach( FailureMessageAccessor f in failures ) { // check failure definition ids // against ones to dismiss: FailureDefinitionId id = f.GetFailureDefinitionId(); if( BuiltInFailures.RoomFailures.RoomNotEnclosed == id ) { a.DeleteWarning( f ); } } return FailureProcessingResult.Continue; } }
This is the mainline of the external command Execute method, which performs the following steps:
Document doc = commandData.Application .ActiveUIDocument.Document; FilteredElementCollector collector = new FilteredElementCollector( doc ); collector.OfClass( typeof( Level ) ); Level level = collector.FirstElement() as Level; Transaction t = new Transaction( doc ); t.Start( "Create unbounded room" ); FailureHandlingOptions failOpt = t.GetFailureHandlingOptions(); failOpt.SetFailuresPreprocessor( new RoomWarningSwallower() ); t.SetFailureHandlingOptions( failOpt ); doc.Create.NewRoom( level, new UV( 0, 0 ) ); t.Commit(); return Result.Succeeded;
Many thanks to Harry for this nice little sample and to Leo for the extensive explanation of the ErrorHandling behaviour!
I have included the former as a new module and external command named CmdPreprocessFailure in The Building Coder samples. Here is version 2011.0.0.64 of the complete Visual Studio solution including the new command.