diff --git a/docs/code/experimental/MlNetCookBookStaticApi.md b/docs/code/experimental/MlNetCookBookStaticApi.md
index 086e3b8e3b..99ce4a8d3c 100644
--- a/docs/code/experimental/MlNetCookBookStaticApi.md
+++ b/docs/code/experimental/MlNetCookBookStaticApi.md
@@ -397,7 +397,7 @@ Here's what you do to save the model to a file, and reload it (potentially in a
```csharp
// Saving and loading happens to 'dynamic' models, so the static typing is lost in the process.
-mlContext.Model.Save(model.AsDynamic, trainData.AsDynamic.Schema, modelPath);
+mlContext.Model.Save(model, trainData, modelPath);
// Potentially, the lines below can be in a different process altogether.
diff --git a/src/Microsoft.ML.StaticPipe/ModelOperationsCatalogExtensions.cs b/src/Microsoft.ML.StaticPipe/ModelOperationsCatalogExtensions.cs
new file mode 100644
index 0000000000..c42b983edc
--- /dev/null
+++ b/src/Microsoft.ML.StaticPipe/ModelOperationsCatalogExtensions.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO;
+using Microsoft.ML.Data;
+
+namespace Microsoft.ML.StaticPipe
+{
+ public static class ModelOperationsCatalogExtensions
+ {
+ ///
+ /// Save statically typed model to the stream.
+ ///
+ /// The model explainability operations catalog.
+ /// The trained model to be saved. Note that this can be , as a shorthand
+ /// for an empty transformer chain. Upon loading with the returned value will
+ /// be an empty .
+ /// The data view with the schema of the input to the transformer. This can be .
+ /// A writeable, seekable stream to save to.
+ public static void Save(this ML.ModelOperationsCatalog catalog, Transformer model, DataView dataView, Stream stream)
+ where TTransformer : class, ITransformer
+ {
+ catalog.Save(model?.AsDynamic, dataView?.AsDynamic.Schema, stream);
+ }
+
+ ///
+ /// Save statically typed model to the stream.
+ ///
+ /// The model explainability operations catalog.
+ /// The trained model to be saved. Note that this can be , as a shorthand
+ /// for an empty transformer chain. Upon loading with the returned value will
+ /// be an empty .
+ /// The data view with the schema of the input to the transformer. This can be .
+ /// Path where model should be saved.
+ public static void Save(this ML.ModelOperationsCatalog catalog, Transformer model, DataView dataView, string filePath)
+ where TTransformer : class, ITransformer
+ {
+ catalog.Save(model?.AsDynamic, dataView?.AsDynamic.Schema, filePath);
+ }
+ }
+}
diff --git a/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs b/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs
index cce1de27b5..dc66dd570d 100644
--- a/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs
+++ b/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs
@@ -147,7 +147,7 @@ private void TrainRegression(string trainDataPath, string testDataPath, string m
var metrics = mlContext.Regression.Evaluate(model.Transform(testData), label: r => r.Target, score: r => r.Prediction);
// Saving and loading happens to 'dynamic' models, so the static typing is lost in the process.
- mlContext.Model.Save(model.AsDynamic, trainData.AsDynamic.Schema, modelPath);
+ mlContext.Model.Save(model, trainData, modelPath);
// Potentially, the lines below can be in a different process altogether.