module DynamicsCRM::XML::MessageBuilder

Public Instance Methods

associate_request(entity_name, id, relationship, relationship_entities=[]) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 269
def associate_request(entity_name, id, relationship, relationship_entities=[])
  modify_association("Associate", entity_name, id, relationship, relationship_entities)
end
build_envelope(action, &block) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 104
def build_envelope(action, &block)
  %Q{
   <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    #{build_header(action)}
    <s:Body>
      #{yield}
    </s:Body>
   </s:Envelope>
  }
end
build_header(action) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 115
def build_header(action)
  if @on_premise
    build_on_premise_header(action)
  else
    build_ocp_header(action)
  end
end
build_ocp_header(action) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 174
def build_ocp_header(action)
  caller_id = @caller_id ? %Q{<CallerId xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">#{@caller_id}</CallerId>} : ""
  %Q{
    <s:Header>
     <a:Action s:mustUnderstand="1">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/#{action}</a:Action>
     #{caller_id}
     <a:MessageID>
      urn:uuid:#{uuid()}
     </a:MessageID>
     <a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo>
     <a:To s:mustUnderstand="1">
      #{@organization_endpoint}
     </a:To>
     <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
     <u:Timestamp u:Id="_0">
      <u:Created>#{get_current_time}</u:Created>
      <u:Expires>#{get_tomorrow_time}</u:Expires>
     </u:Timestamp>
     <EncryptedData Id="Assertion0" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"></EncryptionMethod>
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
       <EncryptedKey>
        <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"></EncryptionMethod>
        <ds:KeyInfo Id="keyinfo">
         <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier">
           #{@key_identifier}
          </wsse:KeyIdentifier>
         </wsse:SecurityTokenReference>
        </ds:KeyInfo>
        <CipherData>
         <CipherValue>
          #{@security_token0}
         </CipherValue>
        </CipherData>
       </EncryptedKey>
      </ds:KeyInfo>
      <CipherData>
       <CipherValue>
        #{@security_token1}
       </CipherValue>
      </CipherData>
     </EncryptedData>
     </o:Security>
    </s:Header>
  }
end
build_ocp_request(username, password, region = "urn:crmna:dynamics.com", login_url = Client::OCP_LOGIN_URL) click to toggle source

Select the right region for your CRM The region can be pulled from the Organization WSDL

urn:crmna:dynamics.com - North America urn:crmemea:dynamics.com - Europe, the Middle East and Africa urn:crmapac:dynamics.com - Asia Pacific

# File lib/dynamics_crm/xml/message_builder.rb, line 29
def build_ocp_request(username, password, region = "urn:crmna:dynamics.com", login_url = Client::OCP_LOGIN_URL)
  %Q{
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
      xmlns:a="http://www.w3.org/2005/08/addressing"
      xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <s:Header>
        <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
        <a:MessageID>urn:uuid:#{uuid()}</a:MessageID>
        <a:ReplyTo>
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <a:To s:mustUnderstand="1">#{login_url}</a:To>
        <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <u:Timestamp u:Id="_0">
            <u:Created>#{get_current_time}</u:Created>
            <u:Expires>#{get_tomorrow_time}</u:Expires>
          </u:Timestamp>
          <o:UsernameToken u:Id="uuid-cdb639e6-f9b0-4c01-b454-0fe244de73af-1">
            <o:Username>#{REXML::Text.new(username).to_s}</o:Username>
            <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
              #{REXML::Text.new(password).to_s}
            </o:Password>
          </o:UsernameToken>
        </o:Security>
      </s:Header>
      <s:Body>
        <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
          <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
            <a:EndpointReference>
              <a:Address>#{region}</a:Address>
            </a:EndpointReference>
          </wsp:AppliesTo>
          <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
        </t:RequestSecurityToken>
      </s:Body>
    </s:Envelope>
  }
end
build_on_premise_header(action) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 123
def build_on_premise_header(action)
  %Q{
    <s:Header>
      <a:Action s:mustUnderstand="1">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/#{action}</a:Action>
      <a:MessageID>urn:uuid:#{uuid()}</a:MessageID>
      <a:ReplyTo>
        <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
      </a:ReplyTo>
      <a:To s:mustUnderstand="1">#{@organization_endpoint}</a:To>
      <o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        #{@timestamp}
        <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
          <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
              <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
              </e:EncryptionMethod>
              <KeyInfo>
                <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                  <X509Data>
                    <X509IssuerSerial>
                      <X509IssuerName>#{@cert_issuer_name}</X509IssuerName>
                      <X509SerialNumber>#{@cert_serial_number}</X509SerialNumber>
                    </X509IssuerSerial>
                  </X509Data>
                </o:SecurityTokenReference>
              </KeyInfo>
              <e:CipherData>
                <e:CipherValue>#{@security_token0}</e:CipherValue>
              </e:CipherData>
            </e:EncryptedKey>
          </KeyInfo>
          <xenc:CipherData>
            <xenc:CipherValue>#{@security_token1}</xenc:CipherValue>
          </xenc:CipherData>
        </xenc:EncryptedData>
        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
          #{@signature}
          <SignatureValue>#{@signature_value}</SignatureValue>
          <KeyInfo>
            <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
              <o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">#{@key_identifier}</o:KeyIdentifier>
            </o:SecurityTokenReference>
          </KeyInfo>
        </Signature>
      </o:Security>
    </s:Header>
  }
end
build_on_premise_request(username, password, region = "", login_url = nil) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 68
def build_on_premise_request(username, password, region = "", login_url = nil)
  %Q{
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
      xmlns:a="http://www.w3.org/2005/08/addressing">
      <s:Header>
        <a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>
        <a:MessageID>urn:uuid:#{uuid()}</a:MessageID>
        <a:ReplyTo>
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <Security s:mustUnderstand="1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <u:Timestamp u:Id="#{uuid()}">
            <u:Created>#{get_current_time}</u:Created>
            <u:Expires>#{get_current_time_plus_hour}</u:Expires>
          </u:Timestamp>
          <UsernameToken u:Id="#{uuid()}">
            <Username>#{REXML::Text.new(username).to_s}</Username>
            <Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">#{REXML::Text.new(password).to_s}</Password>
          </UsernameToken>
        </Security>
        <a:To s:mustUnderstand="1">#{login_url}</a:To>
      </s:Header>
      <s:Body>
        <trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
          <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
            <a:EndpointReference>
              <a:Address>#{region}</a:Address>
            </a:EndpointReference>
          </wsp:AppliesTo>
          <trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
        </trust:RequestSecurityToken>
      </s:Body>
    </s:Envelope>
  }
end
create_request(entity) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 222
def create_request(entity)
  build_envelope('Create') do
    %Q{<Create xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        #{entity.to_xml}
    </Create>}
  end
end
delete_request(entity_name, guid) click to toggle source

Tag name case MATTERS!

# File lib/dynamics_crm/xml/message_builder.rb, line 260
def delete_request(entity_name, guid)
  build_envelope('Delete') do
    %Q{<Delete xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
        <entityName>#{entity_name}</entityName>
        <id>#{guid}</id>
      </Delete>}
  end
end
disassociate_request(entity_name, id, relationship, relationship_entities=[]) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 273
def disassociate_request(entity_name, id, relationship, relationship_entities=[])
  modify_association("Disassociate", entity_name, id, relationship, relationship_entities)
end
execute_request(action, parameters={}) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 296
def execute_request(action, parameters={})

  # Default namespace is /crm/2011/Contracts
  ns_alias = "b"
  # Metadata Service calls are under the /xrm/2011/Contracts schema.
  if ["RetrieveAllEntities", "RetrieveEntityMetadata", "RetrieveEntity", "RetrieveAttribute", "RetrieveMultiple", "RetrieveMetadataChanges"].include?(action)
    ns_alias = 'a'
  end

  parameters = XML::Parameters.new(parameters)
  build_envelope('Execute') do
    %Q{<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <request i:type="#{ns_alias}:#{action}Request" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:b="http://schemas.microsoft.com/crm/2011/Contracts">
       #{parameters.to_xml}
       <a:RequestId i:nil="true" />
       <a:RequestName>#{action}</a:RequestName>
      </request>
     </Execute>}
   end
end
get_current_time() click to toggle source

have a bit of flexiblity in the create time to handle when system clocks are out of sync

# File lib/dynamics_crm/xml/message_builder.rb, line 10
def get_current_time
  # 5.minutes = 5 * 60
  (Time.now - (5 * 60)).utc.strftime '%Y-%m-%dT%H:%M:%SZ'
end
get_current_time_plus_hour() click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 15
def get_current_time_plus_hour
  (Time.now.utc + (60*60)).strftime '%Y-%m-%dT%H:%M:%SZ'
end
get_tomorrow_time() click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 19
def get_tomorrow_time
  (Time.now.utc + (24*60*60)).strftime '%Y-%m-%dT%H:%M:%SZ'
end
modify_association(action, entity_name, id, relationship, relationship_entities=[]) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 277
def modify_association(action, entity_name, id, relationship, relationship_entities=[])
  entities_xml = ""
  relationship_entities.each do |ref|
    entities_xml << ref.to_xml(namespace: "b", camel_case: true)
  end

  build_envelope(action) do
    %Q{<#{action} xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:b="http://schemas.microsoft.com/xrm/2011/Contracts">
          <entityName i:type="string">#{entity_name}</entityName>
          <entityId xmlns:q10="http://schemas.microsoft.com/2003/10/Serialization/" i:type="q10:guid">#{id}</entityId>
          <relationship i:type="b:Relationship">
            <b:PrimaryEntityRole i:nil="true" />
            <b:SchemaName i:type="string">#{relationship}</b:SchemaName>
          </relationship>
          <relatedEntities i:type="b:EntityReferenceCollection">#{entities_xml}</relatedEntities>
       </#{action}>}
  end
end
retrieve_multiple_request(object) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 249
def retrieve_multiple_request(object)
  request = build_envelope('RetrieveMultiple') do
    %Q{
    <RetrieveMultiple xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
      #{object.to_xml}
    </RetrieveMultiple>
    }
  end
end
retrieve_request(entity_name, guid, columns) click to toggle source

Tag name case MATTERS!

# File lib/dynamics_crm/xml/message_builder.rb, line 239
def retrieve_request(entity_name, guid, columns)
  build_envelope('Retrieve') do
    %Q{<Retrieve xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
        <entityName>#{entity_name}</entityName>
        <id>#{guid}</id>
        #{columns.to_xml}
      </Retrieve>}
  end
end
update_request(entity) click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 230
def update_request(entity)
  build_envelope('Update') do
    %Q{<Update xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        #{entity.to_xml}
    </Update>}
  end
end
uuid() click to toggle source
# File lib/dynamics_crm/xml/message_builder.rb, line 5
def uuid
  SecureRandom.uuid
end