Post linking vertex attribute binding not stored

I’m trying to figure out how VAOs work so I wrote a stupid function to test a shader.
In the Vertex Shader I have 2 in variables for passing vertex attribute data.
When I bind these variables directly (using glBindAttribLocation()) to some Vertex Attribute Index and Bind the VBOs to these indices then it works fine.

If I link the program first and let the linker decide the indices of these variables, then query these indices and bind the VBOs to them (as I did in the previous case) , nothing gets drawned. As if the VBOs are not hooked on the indices.

Here is my code.
I’m using OpenTK and C#

As you can see I create a Dictionary with entries for each in variable which I then invoke by name. I’ve checked it and the indices returned are the correct (and the same with the Pre Linking Binding). I have put commends which lines I use in each of the two cases.


private void PureShaderDraw()
        {
            Matrix4 MVMatrix;
            Matrix4 PMatrix;
            float[,] NormalMatrix;
            Dictionary<string, VertexAttribute> VAttribLexicon = new Dictionary<string, VertexAttribute>();

            Shaders.GLSL_Program cProg = Foundation.Global3DObjectCollection.GLSL_ProgramList[_GLSL_ProgramHandle];
            
            if (FirstRun)
            {
                //Uncomment these two Lines for Fixed binding
                //GL.BindAttribLocation(_GLSL_ProgramHandle, 0, "gli_Vertex");
                //GL.BindAttribLocation(_GLSL_ProgramHandle, 1, "gli_Normal");

                GL.BindFragDataLocation(_GLSL_ProgramHandle, 0, "FragColor");

                
                cProg.LinkProgram();
            }

            //If Pre linking fixed Binding occurs, Comment this whole if clause
            if (FirstRun)
            {
                //First get the number of used vertex attribute indices
                int numOfIndices, maxNameLen;
                GL.GetProgram(_GLSL_ProgramHandle, ProgramParameter.ActiveAttributes, out numOfIndices);
                GL.GetProgram(_GLSL_ProgramHandle, ProgramParameter.ActiveAttributeMaxLength, out maxNameLen);

                //Clear the current Entries in the Lexicon.
                VAttribLexicon.Clear();

                //For each attribute index
                for (int i = 0; i < numOfIndices; ++i)
                {
                    int NameLen, attribSize;
                    ActiveAttribType attribType;
                    StringBuilder sBuilder = new StringBuilder();

                    //Read the variable assigned to it.
                    GL.GetActiveAttrib(_GLSL_ProgramHandle, i, maxNameLen, out NameLen, out attribSize, out attribType, sBuilder);
                    //Store an entry in the lexikon.
                    VAttribLexicon.Add(sBuilder.ToString(), new VertexAttribute(sBuilder.ToString(), (uint)i, attribType));
                }
            }

            GL.UseProgram(_GLSL_ProgramHandle);

            MVMatrix = Foundation.RenderingDevice.DeviceState.GetCurrentModelviewMatrix();
            PMatrix = Foundation.RenderingDevice.DeviceState.GetCurrentProjectionMatrix();
            NormalMatrix = Foundation.RenderingDevice.DeviceState.GetCurrentNormalMatrix();

            GL.Uniform3(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "BrickColor"), 1.0f, 0.3f, 0.2f);
            GL.Uniform3(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "MortarColor"), 0.85f, 0.86f, 0.84f);
            GL.Uniform2(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "BrickSize"), 0.30f, 0.15f);
            GL.Uniform2(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "BrickPct"), 0.9f, 0.85f);
            GL.Uniform3(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "LightPosition"), 0.0f, 0.0f, 4.0f);
            GL.UniformMatrix4(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "MVMatrix"), false, ref MVMatrix);
            GL.UniformMatrix4(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "PMatrix"), false, ref PMatrix);
            GL.UniformMatrix3(Foundation.GetUniformLocation(_GLSL_ProgramHandle, "NormalMatrix"), 1, false,
                Foundation.ArrayOperations.ToColumnWiseArrayf(NormalMatrix));

            cProg.VAO.MakeCurrent();

            if (FirstRun)
            {
                Primary.Vertex_VBO.BindData(Primary.VertexArray, 3);
                Primary.Normal_VBO.BindData(Primary.NormalArray, 3);
                Index_VBO.BindData(IndexArray, 3);

                //Uncomment these two Lines for Fixed binding
                //cProg.VAO.BindVBO(0, Primary.Vertex_VBO);
                //cProg.VAO.BindVBO(1, Primary.Normal_VBO);

                //Ccomment these two Lines for Fixed binding
                cProg.VAO.BindVBO(VAttribLexicon["gli_Vertex"].Index, Primary.Vertex_VBO);
                cProg.VAO.BindVBO(VAttribLexicon["gli_Normal"].Index, Primary.Normal_VBO);
            }
            
            //Draw the primitives according to the subdivision method
            if (SubdivisionMethod == MeshSubdivisionMethod.Triangulation)
                GL.DrawElements(BeginMode.Triangles, IndexArray.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
            else
                GL.DrawElements(BeginMode.Quads, IndexArray.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);

            if (FirstRun) FirstRun = false;

            GL.BindVertexArray(0);
            GL.UseProgram(0);
        }