using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil;
using Autodesk.Civil.DatabaseServices;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices.Styles;
namespace ALC_SurfaceBoundery
{
    public class MyCommands
    {
        public static ObjectId SelectSurface()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            ObjectId result = ObjectId.Null;
            PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect surface: ");
            entOpts.SetRejectMessage("...not a surface, try again!:");
            entOpts.AddAllowedClass(typeof(TinSurface), true);
            PromptEntityResult entRes = ed.GetEntity(entOpts);
            if (entRes.Status == PromptStatus.OK) result = entRes.ObjectId;
            return result;
        }
        [CommandMethod("alcSurfaceBounderyFromSurface")]
        public void alcSB()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            CivilDocument civdoc = CivilApplication.ActiveDocument;
            Database db = Application.DocumentManager.MdiActiveDocument.Database;
            Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;
            ed.WriteMessage("\nFirst surface:");
            ObjectId idSurface1= SelectSurface();
            if (idSurface1 == ObjectId.Null) return;
            ed.WriteMessage("\nSecond surface:");
            ObjectId idSurface2 = SelectSurface();
            if (idSurface2 == ObjectId.Null) return;
            using (Transaction trans = tm.StartTransaction())
            {
                try
                {
                    TinSurface s1 = tm.GetObject(idSurface1, OpenMode.ForWrite) as TinSurface;
                    TinSurface s2 = tm.GetObject(idSurface2, OpenMode.ForRead) as TinSurface;
                    ObjectIdCollection objIdCol1 = new ObjectIdCollection ();
                    // list all boundaries off surface 2 from definition 
                    if (s2.BoundariesDefinition.Count > 0)
                    {
                        for (int i = 0; i < s2.BoundariesDefinition.Count; i++)
                        {
                            SurfaceOperationAddBoundary soab = s2.BoundariesDefinition[i];
                            ed.WriteMessage("\n {0}, Type {1}, ", soab.Name.ToString(), soab.BoundaryType.ToString());
                            foreach (SurfaceBoundary sb in soab)
                            {
                                Point3dCollection v = sb.Vertices;
                                ed.WriteMessage(" Vertices: {0}", v.Count);
                                for (int j = 0; j < v.Count; j++)
                                {
                                    ed.WriteMessage("\n" + v[j].ToString());
                                }
                            }
                        }
                    }
                    // check for outer boundery in the Surface defenitions
                    bool isOuterBounderyDefined = false;
                    if (s2.BoundariesDefinition.Count > 0)
                    {
                        for (int i = 0; i < s2.BoundariesDefinition.Count; i++)
                        {
                            SurfaceOperationAddBoundary soab = s2.BoundariesDefinition[i];
                            if (soab[0].BoundaryType == SurfaceBoundaryType.Outer)
                            {
                                Point3dCollection v = soab[0].Vertices;
                                isOuterBounderyDefined = true;
                                // add the vertices as hide boundery to surface 1
                                s1.BoundariesDefinition.AddBoundaries(v, 0.1, SurfaceBoundaryType.Hide, true);
                                ed.WriteMessage("\nOuter boundary found");
                                break;
                            }
                        }
                    }
                    if (!isOuterBounderyDefined)
                    {
                        ed.WriteMessage("\nNo outer boundary found, will be created by Extract Border");
                        // extracte border from surface 2 and add as  hide boundary to surface 1
                        // create a new style called 'example style':
                        ObjectId idStyle = civdoc.Styles.SurfaceStyles.Add("Extraction");
                        // modify the style to display boundaries, exterior only:
                        SurfaceStyle ss = idStyle.GetObject(OpenMode.ForWrite) as SurfaceStyle;
                        ss.GetDisplayStylePlan(SurfaceDisplayStyleType.Boundary).Visible = true;
                        ss.BoundaryStyle.DisplayExteriorBoundaries = true;
                        ss.BoundaryStyle.DisplayInteriorBoundaries = false;
                        // assign this style to the  surface 
                        ObjectId idCurrent = s2.StyleId;
                        s2.StyleId = idStyle;
                        //extract the exterior border
                        ObjectIdCollection borders = s2.ExtractBorder(SurfaceExtractionSettingsType.Plan);
                        s1.BoundariesDefinition.AddBoundaries(borders, 0.1, SurfaceBoundaryType.Hide, true);
                        // change back the style
                        s2.StyleId = idStyle;
                        civdoc.Styles.SurfaceStyles.Remove("Extraction");
                    }
                    // process show and hide boundaries
                    if (s2.BoundariesDefinition.Count > 0)
                    {
                        for (int i = 0; i < s2.BoundariesDefinition.Count; i++)
                        {
                            if (s2.BoundariesDefinition[i].BoundaryType == SurfaceBoundaryType.Hide)
                            {
                                Point3dCollection v = s2.BoundariesDefinition[i][0].Vertices;
                                // add the vertices as show boundery to surface 1
                                ed.WriteMessage("\n Innner boundary (hole) found with {0} vertices", v.Count);
                                for (int j = 0; j < v.Count; j++)
                                {
                                    ed.WriteMessage("\n"  + v[j].ToString());
                                }
                                s1.BoundariesDefinition.AddBoundaries(v, 0.1, SurfaceBoundaryType.Show, true);
                            }
                            if (s2.BoundariesDefinition[i].BoundaryType == SurfaceBoundaryType.Show)
                            {
                                Point3dCollection v = s2.BoundariesDefinition[i][0].Vertices;
                                // add the vertices as show boundery to surface 1
                                ed.WriteMessage("\n innner boundary (island) found with {0} verices", v.Count);
                                s1.BoundariesDefinition.AddBoundaries(v, 0.1, SurfaceBoundaryType.Hide, true);
                            }
                        }
                    }
                    s1.Rebuild();
                }
                catch
                {
                    ed.WriteMessage("\n Does not work");
                }
                trans.Commit();
            }
        }
    }
}With surfaces that has polylines as boundaries it works well, but I could not figure out yet how to handle if your surface for creating the boundary is also build by surfaces as boundaries. 
					
				
			
			
				
	Regards
Andreas Luka (Lu An Jie)
http://www.luka-consult.de
Creator of the LX-Stair App for Civil 3D