Profile View created with .net api does not work

Profile View created with .net api does not work

flycoflyco
Enthusiast Enthusiast
1,140 Views
9 Replies
Message 1 of 10

Profile View created with .net api does not work

flycoflyco
Enthusiast
Enthusiast

hello everyone

I want to check if this only happens on my computer

First of all, if you delete the profile view from the attached drawing, return it to ctrl+Z, and then create a profile view made with .net api, you will find that the created profileview is not deleted.

When tested on Civil 3D 2021, Civil 3D 2022, it worked well, but it did not work on Civil 3D 2023.2.1

 

Below is my code to create the profile view

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;

namespace TestCreateProfileView
{
	public class Class1
	{
		[CommandMethod("CreateProfileView")]
		public void CreateProfileView()
		{

			CivilDocument cdoc = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
			Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
			Database db = doc.Database;
			Editor ed = doc.Editor;

			PromptEntityOptions pEntOpt = new PromptEntityOptions("Select Alignment");
			pEntOpt.SetRejectMessage("Not Alignment");
			pEntOpt.AddAllowedClass(typeof(Alignment), true);
			PromptEntityResult pEntRes = ed.GetEntity(pEntOpt);

			if (pEntRes.Status != PromptStatus.OK)
				return;

			ObjectId alignId = pEntRes.ObjectId;
			try
			{
				using (doc.LockDocument())
				{
					using (Transaction tr = db.TransactionManager.StartTransaction())
					{
						Alignment align = tr.GetObject(alignId, OpenMode.ForWrite) as Alignment;
						ProfileView.Create(alignId, new Point3d(0, 0, 0));
						tr.Commit();
					}
				}
			}
			catch
			{

			}
		}
	}
}

Thanks for reading my long question.

0 Likes
Accepted solutions (1)
1,141 Views
9 Replies
Replies (9)
Message 2 of 10

Kyle-L
Advocate
Advocate
Accepted solution

I am not sure what you mean by "you will find that the created profileview is not deleted".

 

I did the following:

  1. Deleted the existing profile view (named "Alignment - (1)1")
  2. Pressed ctrl+z to undo and the profile view reappeared.
  3. Ran your command, selected the alignment and then a new profile view appeared at 0,0 (named "Alignment - (1)2 (1)"). The existing profile view was still there (see image below)

Not sure this is the result that you wanted.

 

KyleL_0-1677843602924.png

 

By the way, I would not suggest wrapping your transactions in a try catch because if anything goes wrong before you can commit or abort the transaction then your drawing will become unstable. Also, give some feedback in your catch so you can see if anything has gone wrong, such as writing a message in the editor.

 

Here is the code cleaned up a bit:

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;

namespace TestCreateProfileView
{
    public class Class1
    {
        [CommandMethod("CreateProfileView")]
        public void CreateProfileView()
        {

            CivilDocument cdoc = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptEntityOptions pEntOpt = new PromptEntityOptions("Select Alignment");
            pEntOpt.SetRejectMessage("Not Alignment");
            pEntOpt.AddAllowedClass(typeof(Alignment), true);
            PromptEntityResult pEntRes = ed.GetEntity(pEntOpt);

            if (pEntRes.Status != PromptStatus.OK)
                return;

            ObjectId alignId = pEntRes.ObjectId;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    Alignment align = tr.GetObject(alignId, OpenMode.ForRead) as Alignment;
                    ProfileView.Create(alignId, new Point3d(0, 0, 0));
                }
                catch (System.Exception)
                {
                    ed.WriteMessage("\nSomething went wrong.");
                }
                tr.Commit();
            }
            
        }
    }
}

 

Message 3 of 10

flycoflyco
Enthusiast
Enthusiast

Thank you for answer

 

I'am sorry. It meant that the Profile view created with the above source code could not be deleted.

 

I found a difference between the two source codes.

 

1.

try
{
	using (doc.LockDocument())
	{
		using (Transaction tr = db.TransactionManager.StartTransaction())
		{
			ProfileView.Create(alignId, new Point3d(0, 0, 0));
			tr.Commit();
		}
	}
}
catch
{

}

 

2. 

try
{
	//using (doc.LockDocument())
	//{
	//	using (Transaction tr = db.TransactionManager.StartTransaction())
	//	{

			ProfileView.Create(alignId, new Point3d(0, 0, 0));
	//		tr.Commit();
	//	}
	//}
}
catch
{

}

 

The ProfileView created by source code #1 cannot be deleted, but the ProfileView created by source code #2 can be deleted well.

 

Why does it show such a difference?

 

Thank you in advance.

0 Likes
Message 4 of 10

aghensi
Participant
Participant

Hi, sorry to resume this old post, but we're experiencing the same problem and this is the only relevant search result that pops up on the entire internet 😅

 

Our code boils down to this:

 

 var document = Application.DocumentManager.MdiActiveDocument;
 var database = document.Database;
 using var transaction = database.TransactionManager.StartTransaction();
 ProfileView.Create(alignmentId, new Point3d(0,0,0));
 transaction.Commit();

 

The profile view can't be moved or deleted;

If I try to change the layer, I got the message "Object was open for read".

 Searching for that message I found out that I can "unblock" the profile view with an AUDIT command or by closing and re-opening the file.

This is happening on 2 different computers, both using Civil3D 2023.

I can't figure out what it is blocking this, since the transaction is correctly disposed... any idea of what is causing this?

0 Likes
Message 5 of 10

Kyle-L
Advocate
Advocate

ProfileView.Create is a static method and does not need a transaction. Try commenting out the transaction code (lines 3 and 5).

Message 6 of 10

aghensi
Participant
Participant
Wow, that was quick! Thank you for the pointer, it indeed solved the problem!
Have a wonderful day!
0 Likes
Message 7 of 10

aghensi
Participant
Participant

@Kyle-L wrote:

ProfileView.Create is a static method and does not need a transaction.


While this seems to be the case, why do you correlate being a static method to not needing a transaction?

The example in the documentation uses another overload, that is still a static method, but encloses it into a transaction.

Is there a way to be certain if a Civil3D API method needs the transaction or not?

0 Likes
Message 8 of 10

Kyle-L
Advocate
Advocate

Basically, you only need to open a transaction if you are going to interact with the transaction (e.g. open an object for read/write, create an AutoCAD object that needs to be added to the database with AddNewlyCreatedDBObject, etc.).

 

In Civil 3D most of the entity creation is done through static methods and they do not ask for a transaction, so you do not need one. They will probably open a transaction in the background to create the entity.

 

Having said that, there is no reason why using the ProfileView.Create inside a transaction (like it is shown in the docs) should fail, but sometimes the Civil 3D API is a bit buggy. In particular, I have found the ProfileView API very buggy, especially when dealing with bands/band sets. In this case I am guessing the API is somehow committing/disposing the top level transaction (your transaction) when you call the ProfileView.Create method and leaving the drawing/entity/database in an unstable state. This is just a guess though.

 

My rule of thumb is if you can do something outside of a transaction then do not do it inside of one if it can be helped. Also, commit/abort the transaction ASAP, so do as little as possible in a transaction. Opening multiple transactions can be slow, so if you don't need a transaction don't use one.

 

I hope that all makes sense.

Message 9 of 10

aghensi
Participant
Participant
Thanks for the explanation, too bad this is a guessing game and not something that Autodesk clearly explains in the docs.
This is also a bad thing from a flow control perspective: transactions should be there to be able to rollback an entire set of changes to the database if anything goes wrong inside it; if I have to split my code into multiple transactions I can't leverage this feature, leaving the database in an inconsistent, half-baked state.
0 Likes
Message 10 of 10

Jeff_M
Consultant
Consultant

I have code which creates an alignment, profile, and profileview which has been in use since c.2011 and have never had a report of the PV not being able to be moved/erased. So I just did some tests and, sure enough, in Civil 3D 2020 - 2023 I get the same issue. A quick audit does fix it. However, in Civil 3D 2024 & 2025 I do not encounter the issue. So someone at Autodesk must have seen there was something not quite right and corrected it.

 

Since this was never reported as an issue in my software, I can only guess that none of the end users ever tried to move/erase the PV's created with my tools in the same session. And that goes for myself, as well, since I have used them hundreds, perhaps thousands, of times over the last 13 years.

Jeff_M, also a frequent Swamper
EESignature