Skip to content

The Administrative Commands of Windows SharePoint Services

I’ve had a project that I’ve been working on for a while. Back in Microsoft Windows SharePoint Services V2 and SharePoint Portal Server 2003 days it was very difficult to understand where administrative commands were.  Things have gotten a lot better with Windows SharePoint Services 3.0 and Microsoft Office SharePoint Server 2007.  However, there are many times when I’m still unclear on where commands are.

I’ve put together a PDF report (available for free) which shows all of the commands in central administration and many of the site settings commands for WSS 3.0 sites.  I find it valuable to open up and search for words that I know are in the interface but I don’t remember where.  For instance, for a long time I couldn’t remember that Alternate access mappings is on the operations tab not the Application Management tab.  The hope is that this will make it a little easier to find to find the commands you’re looking for.

Please let me know what you think – I need to decide if I should do one for MOSS.

Also, special thanks to Joe Mack who performed the technical verification on this piece for me.

The Worlds Quickest CSS Summary

I can’t quite natively read CSS yet, so I put this little table to help me remember how CSS rules target nodes.

Tag Means Target …
H1 All instances of the specified tag (h1)
.classname Anything where the classname attribute is set to classname
#myid Anything with an ID of myid
Div p All instances of a p tag under a div tag
Div.myclass p All instance of a p tag under a div tag where the div tag has a class name of myclass
Div.myclass, #foo All div tags with a class of myclass *AND* all tags which have an ID of foo

 

The other thing to remember is that if the same definition occurs multiple times or a node is targeted by multiple rules … the last one always wins.

Wikinomics: How Mass Collaboration Changes Everything

Book Review-Wikinomics: How Mass Collaboration Changes Everything

I have to let you in on a secret. I don’t do this blog for you.  Not that anyone could honestly say that they do a blog for one specific person other than themselves.  You see while I’m happy that you (hopefully) find value in this blog.  That isn’t the real reason why I do it.  I do it because I am forgetful.  I need to remember stuff and frankly my memory doesn’t cut it anymore.  So I blog solutions, I collect information, and that way I can find it again – and my friends and clients can find it by searching.  (I’ve told many a client to search my blog for their answers.)

That isn’t to say that some posts aren’t really for you.  There are some that definitely are.  There are posts that exist because there was a client that wanted or needed something documented and they said it was OK to put it on the blog.  There are some intensely altruistic moments when I do truly do things for you – whoever you are – but mostly I don’t.

That’s why Wikinomics is so scary.  What do I mean by scary?  Well, I mean that I still don’t get the social networking animal.  Lawrence Liu has been patiently tutoring me, but still, I’m not 100% in the groove with it.  I still haven’t told you why Wikinomics is so scary … it shows real examples of how the power of social networking has brought about dramatic shifts in the way that we do business.

Everyone reading this blog probably has heard of Linux.  Most folks probably know it is open source.  It’s one of those examples people lay out when they talk about the new way that we’re working.  However, to let you in on a secret, it’s not really all about social networking – Linux is about many things not the least of which is a way for non-Microsoft organizations to make money.

Perhaps the most powerful mass market example – from my perspective – is Wikipedia.  Want to know about something?  Go to Wikipedia.  As long as someone like Stephen Colbert hasn’t been mucking with the pages you can generally get some good information on a variety of topics – for free.  There’s information there that I didn’t even know existed.  For fun, go to Wikipedia and query for your favorite corporation.

After a book full of examples of popular and less than popular examples of how the power of large numbers of people can change the world, I’m wondering what changes are coming that we’re not even seeing yet.  I must admit that I was genuinely concerned when I read the book – but then I became excited.

The real exiting part is what happens when the masses… the millions of productive human beings who work their 9 to 5 shift decide to start interacting with the rest of the world without the barriers of physical space limitations?  What if the tool and die maker comes home and does CAD projects off of a site like Mechanical Turk?  Why?  Not for money, the pay isn’t necessarily all that great but instead for the fun of it.

I know that there are some coding problems that are fun for me to solve, even if the reward isn’t that great.  (Don’t believe me?  How many of you know that I have half a dozen products that I sell – but don’t market?)  What happens when we change our culture from one where we “veg out” into a culture where we “turn on” our brains and start doing productive – or semi-productive work?

If I’ve got you the least bit intrigued, pickup the book Wikinomics: How Mass Collaboration Changes Everything and see what I mean.

Web Content Management Content Type IDs

I needed a quick reference to some of the content type IDs used by MOSS WCM/Publishing features so I dumped the content types out from a publishing site.  This helped me find the content types I needed, I hope it’s useful to you… (Hint: This should now be searchable so the next time you need to know what a content type is — just search for it with your favorite search tool.)

Name

Content Type ID

Description

Item

0x01

Create a new list item.

Reusable HTML

0x01002CF74A4DAE39480396EEA7A4BA2BE5FB

Reusable HTML

Reusable Text

0x01004D5A79BAFA4A4576B79C56FF3D0D662D

Page Output Cache

0x010087D89D279834C94E98E5E1B4A913C67E

Page Output Cache is a system content type template created by the Publishing Resources feature to define cache profiles.

Document

0x0101

Create a new document.

System Page Layout

0x01010007FF3E057FA8AB4AA42FCB67B453FFC1

System Page Layout is a system content type template created by the Publishing Resources feature, and it cannot be modified. To add columns to page layouts in the page layouts gallery and master page gallery, update the Page Layout content type template.

Page Layout

0x01010007FF3E057FA8AB4AA42FCB67B453FFC100E214EEE741181F4E9F7ACC43278EE811

Page Layout is a system content type template created by the Publishing Resources feature. All page layouts will have the column templates from Page Layout added.

System Master Page

0x0101000F1C8B9E0EB4BE489F09807B2C53288F

System Master Page is a system content type template created by the Publishing Resources feature, and it cannot be modified. To add columns to master pages in the page layouts gallery and master page gallery, update the Master Page content type template.

Publishing Master Page

0x0101000F1C8B9E0EB4BE489F09807B2C53288F0054AD6EF48B9F7B45A142F8173F171BD1

Master Page is a system content type template created by the Publishing Resources feature. All master pages will have the column templates from Master Page added.

Office Data Connection File

0x010100629D00608F814DD6AC8A86903AEE72AA

Universal Data Connection File

0x010100B4CBD48E029A4AD8B62CB0E41868F2B0

Provide a standard place for applications, such as Microsoft Office InfoPath, to store data connection information.

System Page

0x010100C568DB52D9D0A14D9B2FDCC96666E9F2

System Page is a system content type template created by the Publishing Resources feature, and it cannot be modified. To add columns to the Pages library, update the Page content type template.

Page

0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39

Page is a system content type template created by the Publishing Resources feature. The column templates from Page will be added to all Pages libraries created by the Publishing feature.

Article Page

0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D

Article Page is a system content type template created by the Publishing Resources feature. It is the associated content type template for the default page layouts used to create article pages in sites that have the Publishing feature enabled.

Welcome Page

0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF390064DEA0F50FC8C147B0B6EA0636C4A7D4

Welcome Page is a system content type template created by the Publishing Resources feature. It is the associated content type template for the default page layout used to create welcome pages in sites that have the Publishing feature enabled.

Redirect Page

0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900FD0E870BA06948879DBD5F9813CD8799

Redirect Page is a system content type template created by the Publishing Resources feature. It is the associated content type template for the redirect page layout

Form

0x010101

Fill out this form.

Picture

0x010102

Upload an image or a photograph.

Unknown Document Type

0x010104

Allows users to upload documents of any content type to a library. Unknown documents will be treated as their original content type in client applications.

Master Page

0x010105

Create a new master page.

User Workflow Document

0x010107

Items for use in user defined workflows.

Wiki Page

0x010108

Create a new wiki page.

Basic Page

0x010109

Create a new basic page.

Web Part Page

0x01010901

Create a new Web Part page.

Link to a Document

0x01010A

Create a link to a document in a different location.

Dublin Core Columns

0x01010B

The Dublin Core metadata element set.

Event

0x0102

Create a new meeting, deadline or other event.

Issue

0x0103

Track an issue or problem.

Announcement

0x0104

Create a new news item, status or other short piece of information.

Link

0x0105

Create a new link to a Web page or other resource.

Contact

0x0106

Store information about a business or personal contact.

Message

0x0107

Create a new message.

Task

0x0108

Track a work item that you or your team needs to complete.

Workflow Task

0x010801

A work item created by a workflow that you or your team needs to complete.

Office SharePoint Server Workflow Task

0x01080100C9C9515DE4E24001905074F980F93160

A work item created by a workflow that you or your team needs to complete.

Administrative Task

0x010802

An administrative work item that an administrator needs to complete.

Workflow History

0x0109

The history of a workflow.

Person

0x010A

SharePointGroup

0x010B

DomainGroup

0x010C

Post

0x0110

Create a new blog post.

Comment

0x0111

Create a new blog comment.

Far East Contact

0x0116

Store information about a business or personal contact.

Folder

0x0120

Create a new folder.

RootOfList

0x012001

Discussion

0x012002

Create a new discussion topic.

 

Dear Mr. InfoPath: (An open letter to the InfoPath Team)

I know we’ve had our issues.  I know that you might think that some of my approaches just don’t work for you.  I’m hoping we can work out our issues though.  Customers need to capture data through forms and having me build every form by hand with development tools just takes too much time.  So I’m hoping that we can work out differences out.  Here’s what I see as our major communications issues are:

1.       You insist that you’re a good friend with my friend SharePoint and yet on several occasions you’ve demonstrated this not to be the case.  Specifically:

a)      You takeover my content types – Despite the fact that you can publish your form templates directly into a content type you require that I put them in a document library.  Why can’t you just publish them to the content type – why do they have to be in a library?

b)      You refuse to be published via a solution package like a good SharePoint citizen – As a result I can’t package things up so that my clients get an InfoPath form and workflow with a single deployment.  If you’re friends with SharePoint shouldn’t you be able to go to a customer together?

c)       You’re not kind enough to find the content type that I want to add the form to – If I select the wrong site (SPWeb) in a site collection (SPSite) and ask you to update the content type you just throw your hands up with an error message that you can’t update the content type.  SharePoint will happily tell you where the content type lives if you ask.

d)      You take over any content type that I ask you to update – I only asked you to associate yourself with the content type and prepare to promote and demote fields.  I didn’t ask you to change what group the content type was in.  SharePoint and I’ll manage the group the content type is in – please leave it alone.

e)      You refuse to let me keep my master template in SharePoint – you keep insisting that it has to be on my local machine.

f)       You won’t promote to user fields in SharePoint – If I want to use you to select users in a SharePoint site I have to do a fancy dance with your Contact Picker and then transform the data on the way out.

g)      You make it difficult to select existing content type fields to promote to – the dialog clearly says it’s all about you and you don’t care what’s already in SharePoint.

h)      You won’t allow me to bind to SharePoint web services to get data – How am I supposed to get data out of SharePoint if you won’t allow me to tell you what the results of the web service will be – I know WSDLs are nice but can’t you bend a little to allow me to give you an example schema?

i)        Why don’t you share your Rich Text with SharePoint? – If I want to promote a rich text field in InfoPath you insist on making it plaintext when it gets to SharePoint – why?

j)        When you promote properties stop locking the fields in SharePoint – Sure you have to propagate to the field but there’s no reason to lock it so that users can’t even see it’s details.

2.       I’ve seen more information about people in the Federal Witness Protection program.  You’ve really got to become less secretive.  Go out in public.  Get some articles written about you.  Maybe even some books that have some real content – not a rehash of what little SDK there is.

3.       Data Connections need context.  It’s great that you let me connect to other data sources but what about when I want to pass parameters to a web service or filter a list of results from SharePoint or do anything that requires any intelligence you run away.  Data connections are only useful if I can get back meaningful results.  I can’t bring back meaningful results if I always get the same results no matter what it is that I’m doing.

So it’s not my intent to enumerate all of your faults, God knows I’ve got enough my own.  But if you could help out just a little.  Get some good sample projects, or something.  It would be greatly appreciated.

Oh by the way, next version doesn’t cut it.  We’ve heard that story before.  I need something now.  If you can’t do it without custom code just show me the code and I’ll create the solutions.

Sincerely

 

Rob Bogue

(One of many who struggles with InfoPath – I’ve heard from many others that feel the same way.)

Domain Certificate Authority Signing InfoPath 2007 Forms

InfoPath forms with custom code and those that have their Security Level set to Full Trust must be signed so that they can be run by the client.  That’s fine but who wants to pay for a code signing certificate for internally developed applications?  If we string together a couple of facts we can quickly realize that we shouldn’t have to pay for code signing certificate if we are developing code that will only ever be used by internal users.

First, certificates work because there are a set of trusted root certificate authorities.  Their responsibility is to issue certificates.  The organizations running the trusted root certificate authorities are responsible for only issuing certificates where the certificate matches the organization requesting the certificate.  They make no judgment about whether the person is good or bad – only that they are who they say they are.  The service that you pay for when you purchase a certificate from a trusted root certificate authority is that they have verified your identity.

Microsoft Windows has a list of trusted root certificate authorities – but when a computer is in a domain, it automatically trusts the Enterprise Certificate Authority for the domain.  The Enterprise certificate authority is an instance of certificate services which comes with Windows Server operating systems.  It allows an administrator to issue certificates.  There are several templates for the kinds of certificates to be issued.  The most common one is for a web server – an SSL certificate – but there are others as well.

Certificate Services has a template for code signing certificates.  If you put everything together you realize that when all of your computers are a member of a domain you can request and get granted a code signing certificate that’s valid for anyone using the certificate in the domain.

Here’s how to do it…

Install Certificate Services

If you don’t have an Enterprise Certificate Authority in your domain, go to a server and …

  1. Click Start- Control Panel-Add/Remove Programs
  2. Click Windows Components
  3. Click the checkmark to the left of Certificate Services
  4. Click Next
  5. Follow the wizard to create an Enterprise Certificate Authority.

Note: There are special precautions for protecting enterprise certificate authorities including creating sub-authorities, and taking the certificate authority offline.  If your organization is large, you should review the risks and guidelines for creating certificate authorities and manage security appropriately.  In smaller organizations it’s generally acceptable to create an enterprise CA and issue certificates from it.

Create a Copy of the Code Signing Template

The default out of box code signing certificate doesn’t allow the certificate’s private key to be exported.  This means that only the user to which the certificate is issued can use it.  Generally you don’t want to have developers to have enough permission to request the certificate themselves.  If you want to be able to move the certificate from user to another you’ll need to make a copy of the Code Signing certificate and change it so it can have exportable keys.  We’re going to show you how to do this.  If you follow these steps choose your duplicated code signing certificate in the following steps.

  1. Click Start-Run and enter certtmpl.msc.
  2. Right click the Code Signing template and select Duplicate.
  3. Enter a name for the new Template.  For instance, add your organization name in front.
  4. Click the Request Handling tab.
  5. Click the Allow private key to be exported.
  6. Click OK.

You now have your own code signing template that can be exported.

Enable the Code Signing Template

By default the  code signing certificate template isn’t available to be issued from your certificate authority.  To do that you need to enable the template which you can do by following these steps…

  1. Click Start-Administrative Tools-Certification Authority
  2. Expand the server that you installed certificate services on
  3. Click the Certificate Templates folder.
  4. Right click the Certificate Templates folder, select New, Certificate Template to Issue.
  5. Click Code Signing and click the OK button.

Now you can issue Code Signing Certificates

Issue the Certificate

Now that everything is in place you can issue the certificate.  Follow these steps to do that…

  1. Open a web browser and navigate to http://server/certsrv where server is the name of the server which you installed certificate services.
  2. Click the Request a certificate link
  3. Click the advanced certificate request link
  4. Click the Create and submit a request to this CA link
  5. In the certificate template drop down box select Code Signing.
  6. Enter a friendly name for the certificate in the friendly name textbox at the end of the page.
  7. Click Submit.  You may be prompted that the web site is requesting a certificate, click Yes.
  8. Click the Install Certificate link. Again you may be warned that you’re getting a certificate, click Yes.

You now have a certificate in your certificates store.  If you’ve not been doing this as the developer (and you probably haven’t), you’ll need to export the certificate and import it into the developer’s account.  You’ll only be able to do this if you created your own code signing template.

Exporting the Certificate

Here’s what you need to do to export the certificate:

  1. Click Start-Run enter certmgr.msc
  2. Expand the Personal Folder
  3. Expand the Certificates folder
  4. Locate the certificate that indicates that its intended purposes is Code Signing.
  5. Right click on that item and select All Tasks-Export
  6. Click Next
  7. Click Yes, export the private key.
  8. Click Next.
  9. Click Next
  10. Enter a password and confirm password.
  11. Click Next
  12. Enter a file name for the exported file
  13. Click Next
  14. Click Finish

You’ve exported the certificate.

Importing the Certificate

If you’ve exported the certificate you can move that over to the user or machine that will be signing the code and follow these steps to import the certificate.

  1. Double click the file to start the Certificate Import Wizard.
  2. Click Next
  3. Click Next
  4. Enter the password you entered when you exported the file.
  5. Click Mark the key as exportable.
  6. Click Next
  7. Click Next
  8. Click Finish
  9. Click OK.

You’ve now imported the certificate file.

Configure InfoPath to Use the Certificate

The final step in this journey is to tell InfoPath to use the certificate.  Do that by following these steps…

  1. Open an InfoPath form in design view.
  2. Click Tools-Form Options
  3. In the category pane, click Security and Trust
  4. Click Sign this form template
  5. Click the Select Certificate button
  6. Select the certificate that you just issued.
  7. Click OK.
  8. Click OK.

OK, you’re done.  That’s all you need to do in order to get a code signing certificate that will sign InfoPath forms that the users of the organization will recognize.

InfoPath 2007 Publishing to SharePoint: Updating the site content type failed

I’ve been struggling for a few days with issues related to InfoPath 2007 publishing to SharePoint.  I thought that I had tried everything.  I had tried publishing to a document library, as a content type, trying to modify content types, etc.  I got a variety of error messages including “Updating the site content type failed”.  This one was my favorite because there wasn’t anything in the content type that I asked InfoPath to update.

I realized later that it was updating the document template but I wasn’t thinking about that when I saw the error message.

What I realized when I dug into the issue is that InfoPath 2007 couldn’t modify the content type because it had been created at the site collection level – not the subsite level that I was doing my testing from.  You can only modify a content type from where it was created.  When I backed up in the wizard and I gave it the URL for the site collection root rather than the sub-site and then rolled forward through the wizard again it worked.

So if you’re having trouble getting InfoPath 2007 to publish to SharePoint … try publishing to the root of the site collection. (I still have other issues this didn’t fix like the fact that a properly derived form isn’t showing up as one to modify – but one problem down.)

Hints for Membership Providers (Authentication Providers) with SharePoint

I’ve done work with membership providers more than a few times now and I have developed a love-hate relationship with them within the context of SharePoint.  It’s not that membership providers don’t work.  They do.  You can absolutely make them work.  However, it’s also true that there are a lot of landmines in the way.  I wanted to provide a few of my experiences with Membership providers that may be helpful for you…

  1. Don’t start with SharePoint – If you’re going to work with Membership Providers in SharePoint – don’t start there.  Build a simple ASP.NET application that has a secure home page.  Make a login page.  Test your membership provider and its configuration settings in ASP.NET first.  Why?  There are less moving parts.  You can run an ASP.NET web site in debug mode by pressing F5.  You don’t have to deal with all of the other things that are going on inside SharePoint.  The fact that first chance exceptions work in ASP.NET (they don’t in SharePoint) you can try to capture the exceptions as they happen.  (If you don’t know about First Chance Exceptions you can go here.)
  2. Build a Shell – Even if you’ve tested the membership provider in ASP.NET there are reasons why SharePoint is different.  Instead of running with the local account you’re running within the context of the application pool.  Because of this you need to be able to see what’s happening between SharePoint and the Membership Provider.  You may need to see all of the call parameters and the return values – and even the exceptions.  So build yourself a passthrough provider which will log the calls, the responses, and the exceptions.  It will make figuring out what’s happening much easier.  (I have a version.  If you want a copy send me an email and I’ll send you a copy of it.  Better yet, if you’re willing to help review it and get it up on CodePlex let me know.)
  3. People Picker is Evil – The people picker is evil.  You’re supposed to be able to specify the provider to use when selecting a user (myProvider:TheUser).  Sometimes that actually works.  It works if you’re in the zone where the provider is the default, but doesn’t always work outside of that.  Add to the problems with the People Picker that you need to remember to add the search wildcard to the entry in the web.config.  So if you are getting stuck adding permissions… start with adding a Policy for the Web application (see Steve Peschka’s post on the SharePoint Products and Technologies team blog titled “Configuring Multiple Authentication Providers for SharePoint 2007”)
  4. Don’t ask everything of the membership provider – One of my clients wanted to login via email address in active directory – and not their UniquePrincipalName.  Although this is technically possible by using the LDAP provider, that may not be the best answer.  It may make more sense to modify the login page rather than trying to get the membership provider to log in on a field other than the ones that it’s used to logging in with.  In fact, on a scale of difficulty modifying the login page is must easier than mucking with membership providers.  I’ve got a forthcoming article on how to create a custom login page for SharePoint. I’ll add a link here when the article goes live.

 

Good luck on your work with membership providers…

System.DirectoryServices.Protocols (a.k.a. LDAP is your friend)

I’ve had the displeasure of trying to do some work with LDAP in .NET lately.  The interfaces are all there but the documentation and error handling isn’t.  (Read: The lights are on but no one is home.)  Because of this I was pleased to find there was a book out on the subject The .NET Developers Guide to Directory Services by Joe Kaplan and Ryan Dunn.

I also had the pleasure of sharing an email conversation with Joe.  I initiated a conversation with him slightly before I was able to pickup the book – because of his activity in the newsgroups.  I quickly figured out I needed to pick up the book and did.  I highly recommend it because the information that is contained in it is both unique — because it doesn’t exist elsewhere — and is easy to understand.  LDAP may be common but it’s not something that most developers do every day.  Back to my point, there were some interesting things that came out of that conversation.  I wanted to highlight them in part to document them and in part to thank Joe for his help.

1) System.DirectoryServices vs. System.DirectoryServices.Protocols – What I was trying to do was to develop a high performance LDAP ASP.NET 2.0 Membership Provider for a project.  In order to do that, I was going to be using LDAP to authenticate a large number of users.  One of the issues with System.DirectoryServices is cleaning up all of the connections quick enough in a high load environment.  The net of the conversation with Joe – which I agreed with wholeheartedly as I began to understand the underlying characteristics of System.DirectoryServices – was if you need to control cleanup of connections use System.DirectoryServices.Protocols.  The end I came to was that I think of System.DirectoryServices as a façade over System.DirectoryServices.Protocols.  Façade is a pattern that makes using something easier.

2) SSL is not your friend – There are lots of things to think about when trying to use SSL to encrypt your LDAP communications.  First, if you are using clients all in a domain, add an Enterprise Certification Authority to the domain.  If you do that the domain controllers will enroll themselves and start accepting SSL connections for LDAP – that’s cool.  If you don’t have all internal clients, you can refer to this KB article to add a third party certificate.  Even with it working (and tested via LDP) you may have a problem when you try to set SecureSocketLayer support.  You may receive a less than helpful DirectoryOperationException(“The server cannot handle directory requests.”) what isn’t quite so amusing about this is that it didn’t even try to communicate with the server.  The solution was to add the port number to the server.  So instead of passing “Server” to open the LdapConnection, I passed “server:636”.  By the way, LDAPS is port 636 – rather than the 389 port used by LDAP.

3) Fast Concurrent Bind isn’t really a bind – In LDAP you bind to associate credentials to your connection so that it can use those credentials to validate your operations.  One of the things that S.DS.P supports is the idea of a Fast Concurrent Bind.  Basically, check my credentials to make sure that they’re OK – and don’t do anything else.  I tried using Fast Concurrent Bind (because it is the fastest way to validate a user) to bind to a connection and then do a search.  So I did my bind and then did my search.  When I tried the search I got an exception – DirectoryOperationException(“An operation error occurred”) when I dug into the network capture I found a deeper message: “LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece”  It was funny because message 5 was a bind with a success response and message ID 6 – the one I got the error on was a search.  The issue at the end of the day I was I was using fast concurrent bind.  So I wasn’t really doing a full bind at all.  I was just authenticating the user.

With Joe’s help I was able to figure out what the issues were … and create a working solution.