Добрый день, коллеги!
Есть задача: сделать веб-сервис, принимающий на вход сложное json-тело.
В ходе реализации столкнулась с двумя проблемами:
1. Не нашла, как описать прием сложного параметра в сервисе, кроме робкого указания на модификаторы [DataContract] и [DataMember]. Подскажите, где-нибудь есть информация об этом?
2. При вызове из Postman сервис возвращает ответ "403 - Вы не имеете разрешения на просмотр этого каталога пли страницы." (скриншот ниже). Нужно ли где-то отдельно прописывать права на доступ к сервисам?
Скриншот ошибки:
Листинг пример json тела запроса.
{ "scoring_events" : [ { "type" : "pageview", "page_url" : "https://bpmonline.com/", "datetime_utc" : "2018-08-08 12:00:12", "responsible_user" : { "name" : "Иван Иванов", "email" : "i.ivanov@yandex.ru", "type" : "user" }, "partner" : { "name" : "ООО Ромашка" "bpm_id" : "783967ef-c629-4f1d-8cd4-3b3dba955ffc", "contact_email" : "n.ivanova@yandex.ru" } }, ... { ... } ] }
листинг сервиса:
namespace Terrasoft.Configuration.WScoringService { using System; <...> #region Class: WScoringService [ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class WScoringService : BaseService { private WScoringServiceResponse wScoringServiceResponse; #region Methods: Public [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] public string AddScoringEvent(List<ScoringEvent> scoring_events) { if (scoring_events.IsEmpty()) wScoringServiceResponse = new WScoringServiceResponse(true, "empty"); else wScoringServiceResponse = new WScoringServiceResponse(true, scoring_events[0].ToString()); return wScoringServiceResponse.ToJsonString(); } #endregion #region DataContract [DataContract] public class ScoringEvent { [DataMember] public string type; [DataMember] public string page_url; [DataMember] public string datetime_utc; [DataMember] public ResponsibleUser responsible_user; [DataMember] public Partner partner; public override string ToString() { string result; result = "type=" + type + ";"; result += "page_url=" + page_url + ";"; result += "datetime_utc=" + datetime_utc + ";"; result += "responsible_user_name=" + responsible_user.name + ";"; result += "partner_name=" + partner.name + ";\n"; return result; } } [DataContract] public struct ResponsibleUser { [DataMember] public string name; [DataMember] public string email; [DataMember] public string type; } [DataContract] public struct Partner { [DataMember] public string name; [DataMember] public string bpm_id; [DataMember] public string contact_email; } #endregion } #endregion #region Class: WScoringServiceResponse public class WScoringServiceResponse { private bool success; private string message; public WScoringServiceResponse() { } public WScoringServiceResponse(bool success, string message = null) { this.success = success; this.message = message; } public string ToJsonString() { string result = "{\"status\":\""; if (success) result += "ok\","; else result += "error\","; result += "\"message\":\"" + message+ "\"}"; return result; } } #endregion }
Нравится
Примеры сервисов можно найти в конфигурации. Например, [DataContract] и [DataMember] применяют в CurrentUserService так:
[DataContract] public class UserCultureInfo { [DataMember(Name = "timeZoneCode")] public string TimeZoneCode { get; set; } [DataMember(Name = "timeZoneName")] public string TimeZoneName { get; set; } [DataMember(Name = "timeZoneId")] public Guid TimeZoneId { get; set; } [DataMember(Name = "cultureId")] public Guid CultureId { get; set; } [DataMember(Name = "cultureName")] public string CultureName { get; set; } [DataMember(Name = "cultureLanguage")] public string CultureLanguage { get; set; } [DataMember(Name = "dateTimeFormatId")] public Guid DateTimeFormatId { get; set; } [DataMember(Name = "dateTimeFormatName")] public string DateTimeFormatName { get; set; } }
По поводу 403, такое бывает, если при отправке запроса к сервису не передать CSRF-токен.
И вот я пишу другой подобный сервис, привожу пример, который у меня заработал
Данные, которые отправляются в сервис:
{ "WCases": [{ "message": "webinar test", "user_crm_id": "CFAC23D8-8EEA-4EB6-A257-0001538F0723" }, { "message": "webinar test 2", "user_crm_id": "CFAC23D8-8EEA-4EB6-A257-0001538F0723" } ] }
Код сервиса:
namespace Terrasoft.Configuration.WCaseService { using System; using System.ServiceModel; using System.ServiceModel.Web; using System.ServiceModel.Activation; using System.Collections.Generic; using Terrasoft.Core; using Terrasoft.Web.Common; using Terrasoft.Configuration.Slack; using System.Runtime.Serialization; #region WCaseService [ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class WCaseService : BaseService { #region init private SystemUserConnection _systemUserConnection; private SystemUserConnection SystemUserConnection { get { return _systemUserConnection ?? (_systemUserConnection = (SystemUserConnection)AppConnection.SystemUserConnection); } } #endregion #region main: endPoints [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] public string ImportData(List<WCaseTemplate> WCases) { string result = ""; if (WCases != null) { foreach (WCaseTemplate wCasein WCases) { result += "message: " + wCase.UserMessage + "\nuser_crm_id: " + wCase.UsrLoginId.ToString() + "\n"; } } else result = "NULL"; return result; } #endregion } #endregion [DataContract] public class WCaseTemplate { [DataMember(Name = "message")] public string UserMessage { get; set; } [DataMember(Name = "user_crm_id")] public Guid UsrLoginId { get; set; } } }