public static XElement ToXElement(this Saml2Statement statement)
        {
            if (statement == null)
            {
                throw new ArgumentNullException(nameof(statement));
            }

            if (statement is Saml2AttributeStatement)
            {
                var attributeStatement = statement as Saml2AttributeStatement;
                var element = new XElement(Saml2Namespaces.Saml2 + "AttributeStatement");

                foreach (var attribute in attributeStatement.Attributes)
                {
                    var attributeElement = new XElement(Saml2Namespaces.Saml2 + "Attribute", new XAttribute("Name", attribute.Name));

                    attributeElement.AddAttributeIfNotNullOrEmpty("FriendlyName", attribute.FriendlyName);
                    attributeElement.AddAttributeIfNotNullOrEmpty("NameFormat", attribute.NameFormat);
                    attributeElement.AddAttributeIfNotNullOrEmpty("OriginalIssuer", attribute.OriginalIssuer);

                    foreach(var value in attribute.Values)
                    {
                        attributeElement.Add(new XElement(Saml2Namespaces.Saml2 + "AttributeValue", value));
                    }

                    element.Add(attributeElement);
                }

                return element;
            }
            else
            {
                throw new ArgumentNullException(nameof(statement));
            }
        }
        /// <summary>
        /// Create XElement for the Saml2IdPEntry.
        /// </summary>
        public XElement ToXElement()
        {
            var idpEntryElement = new XElement(Saml2Namespaces.Saml2P + "IDPEntry");

            idpEntryElement.AddAttributeIfNotNullOrEmpty("ProviderID", ProviderId.Id);
            idpEntryElement.AddAttributeIfNotNullOrEmpty("Name", Name);
            idpEntryElement.AddAttributeIfNotNullOrEmpty("Loc", Location?.OriginalString);

            return idpEntryElement;
        }
        /// <summary>
        /// Serializes the request to a Xml message.
        /// </summary>
        /// <returns>XElement</returns>
        public XElement ToXElement()
        {
            var x = new XElement(Saml2Namespaces.Saml2P + LocalName);

            x.Add(base.ToXNodes());
            x.AddAttributeIfNotNullOrEmpty("AssertionConsumerServiceURL", AssertionConsumerServiceUrl);
            x.AddAttributeIfNotNullOrEmpty("AttributeConsumingServiceIndex", AttributeConsumingServiceIndex);

            return x;
        }
        /// <summary>
        /// Create XElement for the Saml2NameIdentifier.
        /// </summary>
        /// <param name="nameIdentifier"></param>
        /// <returns></returns>
        public static XElement ToXElement(this Saml2NameIdentifier nameIdentifier)
        {
            if(nameIdentifier == null)
            {
                throw new ArgumentNullException(nameof(nameIdentifier));
            }

            var nameIdElement = new XElement(Saml2Namespaces.Saml2 + "NameID",
                            nameIdentifier.Value);
            nameIdElement.AddAttributeIfNotNullOrEmpty("Format", nameIdentifier.Format);
            nameIdElement.AddAttributeIfNotNullOrEmpty("NameQualifier", nameIdentifier.NameQualifier);
            nameIdElement.AddAttributeIfNotNullOrEmpty("SPNameQualifier", nameIdentifier.SPNameQualifier);
            nameIdElement.AddAttributeIfNotNullOrEmpty("SPProvidedID", nameIdentifier.SPProvidedId);

            return nameIdElement;
        }
        /// <summary>
        /// Serializes the request to a Xml message.
        /// </summary>
        /// <returns>XElement</returns>
        public XElement ToXElement()
        {
            var x = new XElement(Saml2Namespaces.Saml2P + LocalName);

            x.Add(base.ToXNodes());
            x.AddAttributeIfNotNullOrEmpty("AssertionConsumerServiceURL", AssertionConsumerServiceUrl);
            x.AddAttributeIfNotNullOrEmpty("AttributeConsumingServiceIndex", AttributeConsumingServiceIndex);

            // Add parameter for nameid policy
            var n = new XElement(Saml2Namespaces.Saml2P + NameIdPolicy);
            n.AddAttributeIfNotNullOrEmpty("AllowCreate", NameIdPolicyAllowCreate);
            n.Value = string.Empty;
            x.Add(n);
            
            return x;
        }
        public void XmlHelpers_AddAttributeIfNotNullOrEmpty_IgnoresNull()
        {
            var e = new XElement("xml");

            e.AddAttributeIfNotNullOrEmpty("attribute", null);

            e.Attribute("attribute").Should().BeNull();
        }
        /// <summary>
        /// Serializes the request to a Xml message.
        /// </summary>
        /// <returns>XElement</returns>
        public XElement ToXElement()
        {
            var x = new XElement(Saml2Namespaces.Saml2P + LocalName);

            x.Add(base.ToXNodes());
            x.AddAttributeIfNotNullOrEmpty("AssertionConsumerServiceURL", AssertionConsumerServiceUrl);
            x.AddAttributeIfNotNullOrEmpty("AttributeConsumingServiceIndex", AttributeConsumingServiceIndex);

            if (NameIdPolicy != null && (NameIdPolicy.AllowCreate || NameIdPolicy.Format != NameIdFormat.Transient))
            {
                var nameIdFormat = NameIdPolicy.Format.GetString();
                var allowCreate = NameIdPolicy.AllowCreate ? "1" : "0";
                x.Add(new XElement(Saml2Namespaces.Saml2P + "NameIDPolicy", new XAttribute("AllowCreate", allowCreate), new XAttribute("Format", nameIdFormat)));
            }

            return x;
        }
        public void XmlHelpers_AddAttributeIfNotNullOrEmpty_IgnoresObjectWithEmptyToString()
        {
            var e = new XElement("xml");

            e.AddAttributeIfNotNullOrEmpty("attribute", new EmptyToString());

            e.Attribute("attribute").Should().BeNull();
        }
        /// <summary>
        /// Serializes the request to a Xml message.
        /// </summary>
        /// <returns>XElement</returns>
        public XElement ToXElement()
        {
            var x = new XElement(Saml2Namespaces.Saml2P + "AuthnRequest");

            x.Add(base.ToXNodes());
            x.AddAttributeIfNotNullOrEmpty("AssertionConsumerServiceURL", AssertionConsumerServiceUrl);

            return x;
        }
        public void XmlHelpers_AddAttributeIfNotNullOrEmpty_Adds()
        {
            var e = new XElement("xml");

            e.AddAttributeIfNotNullOrEmpty("attribute", "value");

            e.Attribute("attribute").Should().NotBeNull().And.Subject.Value
                .Should().Be("value");
        }
        public void XmlHelpers_AddAttributeIfNotNullOrEmpty_HandlesUri()
        {
            var e = new XElement("xml");

            string uri = "http://some.example.com/";
            e.AddAttributeIfNotNullOrEmpty("attribute", new Uri(uri));

            e.Attribute("attribute").Should().NotBeNull().And.Subject.Value.Should().Be(uri);
        }
        public void XmlHelpers_AddAttributeIfNotNullOrEmpty_HandlesNamespace()
        {
            var e = new XElement("xml");

            var ns = XNamespace.Get("someNamespace");

            e.AddAttributeIfNotNullOrEmpty(ns + "attribute", "");

            e.Attribute(ns + "attribute").Should().BeNull();
        }
        private static XElement ToXElement(Saml2AttributeStatement attributeStatement)
        {
            var element = new XElement(Saml2Namespaces.Saml2 + "AttributeStatement");

            foreach (var attribute in attributeStatement.Attributes)
            {
                var attributeElement = new XElement(Saml2Namespaces.Saml2 + "Attribute", new XAttribute("Name", attribute.Name));

                attributeElement.AddAttributeIfNotNullOrEmpty("FriendlyName", attribute.FriendlyName);
                attributeElement.AddAttributeIfNotNullOrEmpty("NameFormat", attribute.NameFormat);
                attributeElement.AddAttributeIfNotNullOrEmpty("OriginalIssuer", attribute.OriginalIssuer);

                foreach (var value in attribute.Values)
                {
                    attributeElement.Add(new XElement(Saml2Namespaces.Saml2 + "AttributeValue", value));
                }

                element.Add(attributeElement);
            }

            return element;
        }
        public XElement ToXElement()
        {
            var x = new XElement(Saml2Namespaces.Saml2P + LocalName);

            x.Add(base.ToXNodes());
            x.AddAttributeIfNotNullOrEmpty("AssertionConsumerServiceURL", AssertionConsumerServiceUrl);
            x.AddAttributeIfNotNullOrEmpty("AttributeConsumingServiceIndex", AttributeConsumingServiceIndex);

            AddNameIdPolicy(x);

            if (RequestedAuthnContext != null && RequestedAuthnContext.ClassRef != null)
            {
                x.Add(new XElement(Saml2Namespaces.Saml2P + "RequestedAuthnContext",
                    new XAttribute("Comparison", RequestedAuthnContext.Comparison.ToString().ToLowerInvariant()),

                    // Add the classref as original string to avoid URL normalization
                    // and make sure the emitted value is exactly the configured.
                    new XElement(Saml2Namespaces.Saml2 + "AuthnContextClassRef",
                        RequestedAuthnContext.ClassRef.OriginalString)));
            }

            return x;
        }
        /// <summary>
        /// Create XElement for the Saml2Scoping.
        /// </summary>
        public XElement ToXElement()
        {
            var scopingElement = new XElement(Saml2Namespaces.Saml2P + "Scoping");

            if (ProxyCount.HasValue && ProxyCount.Value >= 0)
            {
                scopingElement.AddAttributeIfNotNullOrEmpty("ProxyCount", ProxyCount);
            }

            if (IdPEntries.Count > 0)
            {
                scopingElement.Add(new XElement(
                    Saml2Namespaces.Saml2P + "IDPList",
                    IdPEntries.Select(x => x.ToXElement())));
            }

            scopingElement.Add(RequesterIds.Select(x =>
            new XElement(Saml2Namespaces.Saml2P + "RequesterID", x.Id)));

            return scopingElement;
        }
        /// <summary>
        /// Writes out the conditions as an XElement.
        /// </summary>
        /// <param name="conditions">Conditions to create xml for.</param>
        /// <returns>XElement</returns>
        public static XElement ToXElement(this Saml2Conditions conditions)
        {
            if(conditions == null)
            {
                throw new ArgumentNullException(nameof(conditions));
            }

            var xml = new XElement(Saml2Namespaces.Saml2 + "Conditions");

            xml.AddAttributeIfNotNullOrEmpty("NotOnOrAfter",
                    conditions.NotOnOrAfter?.ToSaml2DateTimeString());

            foreach(var ar in conditions.AudienceRestrictions)
            {
                xml.Add(new XElement(Saml2Namespaces.Saml2 + "AudienceRestriction",
                    ar.Audiences.Select(a =>
                    new XElement(Saml2Namespaces.Saml2 + "Audience", a.OriginalString))));
            }

            return xml;
        }
        public void XmlHelpers_AddAttributeIfNotNullOrEmtpy_TimeSpanSerializedCorrectly()
        {
            // It might be tempting in the implementation to call value.ToString()
            // instead of passing in the value. That would make types that have
            // special XML Serialization formats fail. This test ensures that
            // nobody takes that shortcut without handling the special cases.

            var e = new XElement("xml");

            e.AddAttributeIfNotNullOrEmpty("attribute", new TimeSpan(2, 17, 32));

            e.Attribute("attribute").Should().NotBeNull().And.Subject.Value.Should().Be("PT2H17M32S");
        }
        /// <summary>
        /// Serializes the request to a Xml message.
        /// </summary>
        /// <returns>XElement</returns>
        public XElement ToXElement()
        {
            // Create base element and set attributes
            var x = new XElement(Saml2Namespaces.Saml2P + LocalName);
            x.Add(base.ToXNodes());
            x.AddAttributeIfNotNullOrEmpty("AssertionConsumerServiceURL", AssertionConsumerServiceUrl);
            x.AddAttributeIfNotNullOrEmpty("AttributeConsumingServiceIndex", AttributeConsumingServiceIndex);

            // Add parameter for nameid policy
            if (NameIdPolicyAllowCreate != null)
            {
                var nameid = new XElement(Saml2Namespaces.Saml2P + NameIdPolicy);
                nameid.AddAttributeIfNotNullOrEmpty("AllowCreate", NameIdPolicyAllowCreate);
                x.Add(nameid);
            }

            // Add requested authentication context
            if (RequestedAuthenticationContext != null && RequestedAuthenticationContext != string.Empty)
            {
                var authc = new XElement(Saml2Namespaces.Saml2P + RequestedAuthnContext);
                authc.AddAttributeIfNotNullOrEmpty("Comparison", "exact");
                var authcRef = new XElement(Saml2Namespaces.Saml2 + AuthnContextClassRef);
                authcRef.Value = RequestedAuthenticationContext;
                authc.Add(authcRef);
                x.Add(authc);
            }

            return x;
        }
        /// <summary>
        /// Serializes the message into wellformed Xml.
        /// </summary>
        /// <returns>string containing the Xml data.</returns>
        public override string ToXml()
        {
            var x = new XElement(Saml2Namespaces.Saml2P + LocalName);

            x.Add(base.ToXNodes());
            var nameId = new XElement(Saml2Namespaces.Saml2 + "NameID",
                NameId.Value);
            nameId.AddAttributeIfNotNullOrEmpty("Format", NameId.Format);
            x.Add(nameId);

            x.Add(new XElement(Saml2Namespaces.Saml2P + "SessionIndex",
                SessionIndex));

            return x.ToString();
        }
        /// <summary>
        /// Serializes the request to a Xml message.
        /// </summary>
        /// <returns>XElement</returns>
        public XElement ToXElement()
        {
            var x = new XElement(Saml2Namespaces.Saml2P + LocalName);

            x.Add(base.ToXNodes());
            x.AddAttributeIfNotNullOrEmpty("AssertionConsumerServiceURL", AssertionConsumerServiceUrl);
            x.AddAttributeIfNotNullOrEmpty("AttributeConsumingServiceIndex", AttributeConsumingServiceIndex);

            if (SigningCertificate != null)
            {
                // TODO: we need a parameter for whether or not to include the cert
                var doc = x.ToXmlDocument();
                doc.Sign(SigningCertificate, false);
                x = doc.ToXDocument();
            }

            return x;
        }