/// <summary> /// Assemble a document from the given template, answers and settings. /// </summary> /// <param name="template">An instance of the Template class.</param> /// <param name="answers"> /// Either an XML answer string, or a string containing encoded /// interview answers as posted from a HotDocs browser interview. /// </param> /// <param name="settings">An instance of the AssembleDocumentResult class.</param> /// <include file="../Shared/Help.xml" path="Help/string/param[@name='logRef']" /> /// <returns>An AssemblyResult object containing all the files and data resulting from the request.</returns> public AssembleDocumentResult AssembleDocument(Template template, TextReader answers, AssembleDocumentSettings settings, string logRef = "") { if (template == null) { throw new ArgumentNullException("template"); } using (var client = new HttpClient()) { AssembleDocumentResult adr = null; var packageTemplateLocation = (PackageTemplateLocation)template.Location; var packageId = packageTemplateLocation.PackageID; var of = ConvertFormat(settings.Format); var timestamp = DateTime.UtcNow; var hmac = HMAC.CalculateHMAC( SigningKey, timestamp, SubscriberId, packageId, template.FileName, false, logRef, of, settings.Settings); var urlBuilder = new StringBuilder().AppendFormat("{0}/assemble/{1}/{2}/{3}?" + "format={4}&" + "encodefilenames={5}&" + "billingref={6}{7}", HostAddress, SubscriberId, packageId, Uri.EscapeDataString(template.FileName), of, true, Uri.EscapeDataString(logRef), GetRetrieveFromHubParam()); if (settings.Settings != null) { foreach (var kv in settings.Settings) { urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? ""); } } var request = new HttpRequestMessage { RequestUri = new Uri(urlBuilder.ToString()), Method = HttpMethod.Post }; request.Headers.Add("x-hd-date", timestamp.ToString("yyyy-MM-ddTHH:mm:ssZ")); request.Headers.Authorization = new AuthenticationHeaderValue("basic", hmac); var stringContent = answers == null ? new StringContent(string.Empty) : new StringContent(answers.ReadToEnd()); request.Content = stringContent; request.Content.Headers.TryAddWithoutValidation("Content-Type", "text/xml"); var result = client.SendAsync(request).Result; var parser = new MultipartMimeParser(); HandleStatusCode(result); var streamResult = result.Content.ReadAsStreamAsync().Result; var streams = new List <MemoryStream>(); using (var resultsStream = new MemoryStream()) { // Each part is written to a file whose name is specified in the content-disposition // header, except for the AssemblyResult part, which has a file name of "meta0.xml", // and is parsed into an AssemblyResult object. parser.WritePartsToStreams( streamResult, h => { var fileName = GetFileNameFromHeaders(h); if (fileName == null) { return(Stream.Null); } if (fileName.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase)) { return(resultsStream); } var stream = new MemoryStream(); streams.Add(stream); return(stream); }, (new ContentType(result.Content.Headers.ContentType.ToString())).Boundary); if (resultsStream.Position <= 0) { return(null); } resultsStream.Position = 0; var serializer = new XmlSerializer(typeof(AssemblyResult)); var asmResult = (AssemblyResult)serializer.Deserialize(resultsStream); if (asmResult == null) { return(adr); } for (var i = 0; i < asmResult.Documents.Length; i++) { asmResult.Documents[i].Data = streams[i].ToArray(); streams[i].Dispose(); } adr = Util.ConvertAssemblyResult(template, asmResult, settings.Format); } return(adr); } }
public AssembleDocumentResult AssembleDocument(Template template, TextReader answers, AssembleDocumentSettings settings, string logRef) { using (var client = new HttpClient()) { AssembleDocumentResult adr = null; var stringContent = new StringContent(answers.ReadToEnd()); var packageTemplateLocation = (PackageTemplateLocation)template.Location; string packageId = packageTemplateLocation.PackageID; OutputFormat of = ConvertFormat(settings.Format); var urlBuilder = new StringBuilder(string.Format(HostAddress + "/assemble/0/{0}/{1}?format={2}&encodefilenames={3}", packageId, HttpUtility.UrlEncode(template.FileName), of, true)); if (settings.Settings != null) { foreach (var kv in settings.Settings) { urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? ""); } } HttpResponseMessage result = client.PostAsync(urlBuilder.ToString(), stringContent).Result; var _parser = new MultipartMimeParser(); HandleErrorStream(result, result.IsSuccessStatusCode); Stream streamResult = result.Content.ReadAsStreamAsync().Result; string outputDir = Path.GetTempPath(); Directory.CreateDirectory(outputDir); using (var resultsStream = new MemoryStream()) { // Each part is written to a file whose name is specified in the content-disposition // header, except for the AssemblyResult part, which has a file name of "meta0.xml", // and is parsed into an AssemblyResult object. _parser.WritePartsToStreams( streamResult, h => { string fileName = GetFileNameFromHeaders(h); if (fileName != null) { if (fileName.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase)) { return(resultsStream); } return(new FileStream(Path.Combine(outputDir, fileName), FileMode.Create)); } return(Stream.Null); }, (new ContentType(result.Content.Headers.ContentType.ToString())).Boundary); if (resultsStream.Position > 0) { resultsStream.Position = 0; var serializer = new XmlSerializer(typeof(AssemblyResult)); var asmResult = (AssemblyResult)serializer.Deserialize(resultsStream); if (asmResult != null) { adr = Util.ConvertAssemblyResult(template, asmResult, settings.Format); } } } return(adr); } }
/// <summary> /// GetInterview returns an HTML fragment suitable for inclusion in any standards-mode web page, which embeds a HotDocs /// interview /// directly in that web page. /// </summary> /// <param name="template">The template for which to return an interview.</param> /// <param name="answers">The answers to use when building an interview.</param> /// <param name="settings">The <see cref="InterviewSettings" /> to use when building an interview.</param> /// <param name="markedVariables"> /// The variables to highlight to the user as needing special attention. /// This is usually populated with <see cref="AssembleDocumentResult.UnansweredVariables" /> /// from <see cref="AssembleDocument" />. /// </param> /// <include file="../Shared/Help.xml" path="Help/string/param[@name='logRef']" /> /// <returns>Returns the results of building the interview as an <see cref="InterviewResult" /> object.</returns> public InterviewResult GetInterview(Template template, TextReader answers, InterviewSettings settings, IEnumerable <string> markedVariables, string logRef = "") { if (template == null) { throw new ArgumentNullException("template"); } if (settings == null) { throw new ArgumentNullException("settings"); } using (var client = new HttpClient()) { var packageTemplateLocation = (PackageTemplateLocation)template.Location; var packageId = packageTemplateLocation.PackageID; var timestamp = DateTime.UtcNow; var hmac = HMAC.CalculateHMAC( SigningKey, timestamp, SubscriberId, packageId, template.FileName, false, logRef, settings.Format, settings.InterviewFilesUrl, settings.Settings); var urlBuilder = new StringBuilder().AppendFormat("{0}/interview/{1}/{2}/{3}?" + "format={4}&" + "markedvariables{5}&" + "tempimageurl={6}&" + "encodeFileNames={7}&" + "billingref={8}" + "{9}", HostAddress, SubscriberId, packageId, Uri.EscapeDataString(template.FileName), settings.Format, markedVariables != null && markedVariables.Any() ? "=" + Uri.EscapeDataString(string.Join(",", settings.MarkedVariables)) : null, Uri.EscapeDataString(settings.InterviewFilesUrl), true, Uri.EscapeDataString(logRef), GetRetrieveFromHubParam()); foreach (var kv in settings.Settings) { urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? ""); } var request = new HttpRequestMessage { RequestUri = new Uri(urlBuilder.ToString()), Method = HttpMethod.Post }; request.Headers.Add("x-hd-date", timestamp.ToString("yyyy-MM-ddTHH:mm:ssZ")); request.Headers.Authorization = new AuthenticationHeaderValue("basic", hmac); var stringContent = answers == null ? new StringContent(string.Empty) : new StringContent(answers.ReadToEnd()); request.Content = stringContent; var result = client.SendAsync(request).Result; HandleStatusCode(result); var streamResult = result.Content.ReadAsStreamAsync().Result; var parser = new MultipartMimeParser(); var outputDir = Path.GetTempPath(); Directory.CreateDirectory(outputDir); var streams = new List <MemoryStream>(); using (var resultsStream = new MemoryStream()) { // Each part is written to a file whose name is specified in the content-disposition // header, except for the BinaryObject[] part, which has a file name of "meta0.xml", // and is parsed into an BinaryObject[] object. parser.WritePartsToStreams( streamResult, h => { var fileName = GetFileNameFromHeaders(h); if (string.IsNullOrEmpty(fileName)) { return(Stream.Null); } if (fileName.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase)) { return(resultsStream); } // The following stream will be closed by the parser var stream = new MemoryStream(); streams.Add(stream); return(stream); }, (new ContentType(result.Content.Headers.ContentType.ToString())).Boundary); if (resultsStream.Position <= 0) { return(null); } resultsStream.Position = 0; var serializer = new XmlSerializer(typeof(BinaryObject[])); var binObjects = (BinaryObject[])serializer.Deserialize(resultsStream); for (var i = 0; i < binObjects.Length; i++) { binObjects[i].Data = streams[i].ToArray(); streams[i].Dispose(); } var interviewContent = Util.ExtractString(binObjects[0]); return(new InterviewResult { HtmlFragment = interviewContent }); } } }
public InterviewResult GetInterview(Template template, TextReader answers, InterviewSettings settings, IEnumerable <string> markedVariables, string logRef) { using (var client = new HttpClient()) { var packageTemplateLocation = (PackageTemplateLocation)template.Location; string packageId = packageTemplateLocation.PackageID; var urlBuilder = new StringBuilder(string.Format( HostAddress + "/interview/0/{0}/{1}?format={2}&markedvariables{3}&tempimageurl={4}&encodeFileNames={5}", packageId, HttpUtility.UrlEncode(template.FileName), settings.Format, markedVariables != null ? "=" + HttpUtility.UrlEncode(string.Join(",", settings.MarkedVariables)) : null, HttpUtility.UrlEncode(settings.InterviewFilesUrl), true)); foreach (var kv in settings.Settings) { urlBuilder.AppendFormat("&{0}={1}", kv.Key, kv.Value ?? ""); } StringContent stringContent = answers == null ? new StringContent(String.Empty) : new StringContent(answers.ReadToEnd()); HttpResponseMessage result = client.PostAsync(urlBuilder.ToString(), stringContent).Result; HandleErrorStream(result, result.IsSuccessStatusCode); Stream streamResult = result.Content.ReadAsStreamAsync().Result; if (!result.IsSuccessStatusCode) { using (var streamReader = new StreamReader(streamResult)) { string error = streamReader.ReadToEnd(); throw new Exception(error); } } var parser = new MultipartMimeParser(); string outputDir = Path.GetTempPath(); Directory.CreateDirectory(outputDir); using (var resultsStream = new MemoryStream()) { // Each part is written to a file whose name is specified in the content-disposition // header, except for the BinaryObject[] part, which has a file name of "meta0.xml", // and is parsed into an BinaryObject[] object. parser.WritePartsToStreams( streamResult, h => { string fileName = GetFileNameFromHeaders(h); if (!string.IsNullOrEmpty(fileName)) { if (fileName.Equals("meta0.xml", StringComparison.OrdinalIgnoreCase)) { return(resultsStream); } // The following stream will be closed by the parser return(new FileStream(Path.Combine(outputDir, fileName), FileMode.Create)); } return(Stream.Null); }, (new ContentType(result.Content.Headers.ContentType.ToString())).Boundary); if (resultsStream.Position > 0) { resultsStream.Position = 0; var serializer = new XmlSerializer(typeof(BinaryObject[])); var binObjects = (BinaryObject[])serializer.Deserialize(resultsStream); string interviewContent = Util.ExtractString(binObjects[0]); return(new InterviewResult { HtmlFragment = interviewContent }); } return(null); } } }