using System; using System.Linq; using System.Net; using System.ServiceModel; using System.ServiceModel.Activation; using System.Web.Security; using GeneralApi.Core.Repositories; using GeneralApi.Core.Services; using Microsoft.Practices.ServiceLocation; using NHibernate.Validator.Engine; using Taloyhtio.GeneralApi.Common; using Taloyhtio.GeneralApi.Common.Extensions; using Taloyhtio.GeneralApi.Core.Common; using Taloyhtio.GeneralApi.Core.Entities; using Taloyhtio.GeneralApi.Core.Services; using WcfRestContrib.ServiceModel.Description; using TaloyhtioIntegration_resx = Taloyhtio.GeneralApi.Resources.Resources.TaloyhtioIntegration; using WebException = WcfRestContrib.ServiceModel.Web.Exceptions.WebException; namespace Taloyhtio.GeneralApi.WcfService { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "TaloyhtioIntegration" in code, svc and config file together. // NOTE: In order to launch WCF Test Client for testing this service, please select TaloyhtioIntegration.svc or TaloyhtioIntegration.svc.cs at the Solution Explorer and start debugging. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class TaloyhtioIntegration : ITaloyhtioIntegration { public void SaveCondoInformation(Taloyhtio.GeneralApi.Common.DTO.Condo c) { var securityContext = this.ensureAuthorized(); if (c == null) { throw new ArgumentNullException("condo"); } // current assumption is that business id is login name //string businessIdPMC = HttpContext.Current.User.Identity.Name; string businessIdPMC = securityContext.PrimaryIdentity.Name; var condoRepository = ServiceLocator.Current.GetInstance(); var existingCondo = condoRepository.GetByBusinessId(c.BusinessId); if (existingCondo != null) { // pmc may update only their own condos if (existingCondo.BusinessIdPMC != businessIdPMC) { throw new WebException(HttpStatusCode.Unauthorized, string.Format(TaloyhtioIntegration_resx.SecurityIncorrectBusinessIdPMC, businessIdPMC, existingCondo.BusinessId)); } // we can't update properties of existing Condo before validation, because // if validation will fail, UnitOfWork will anyway Commit changes even despite of the fact // that condoRepository.Save(condo) was not called. See http://stackoverflow.com/questions/1380581/nhibernate-commit-db-changes-without-explict-call-to-save-or-update // for details. It happens because existingCondo is attached to session and there is no need to call // ISession.SaveOrUpdate() // existingCondo.OfficialName = c.OfficialName; // existingCondo.Address = c.Address; // existingCondo.Postcode = c.Postcode; // existingCondo.Town = c.Town; // existingCondo.BuildingsType = c.BuildingsType; // existingCondo.BuildingsNumber = c.BuildingsNumber; // existingCondo.StaircasesNumber = c.StaircasesNumber; // existingCondo.BuildingYear = c.BuildingYear; // existingCondo.LastUpdated = DateTime.Now; } // var condo = // new Condo // { // BusinessId = c.BusinessId, // BusinessIdPMC = businessIdPMC, // OfficialName = c.OfficialName, // Address = c.Address, // Postcode = c.Postcode, // Town = c.Town, // BuildingsType = c.BuildingsType, // BuildingsNumber = c.BuildingsNumber, // StaircasesNumber = c.StaircasesNumber, // BuildingYear = c.BuildingYear, // LastUpdated = DateTime.Now // }; var mapper = ServiceLocator.Current.GetInstance>(); var condo = mapper.Map(c); // the following properties are not comming from client. They are ignored in AutoMapper // profile configuration (see DtoProfile) and should be set manually condo.BusinessIdPMC = businessIdPMC; condo.LastUpdated = DateTime.Now; var validator = ServiceLocator.Current.GetInstance(); var errors = validator.Validate(condo); if (!errors.IsNullOrEmpty()) { // var fault = new CustomFaultException // {Reason = string.Join("\n", errors.Select(e => e.ToString()).ToArray())}; // throw new FaultException(fault); throw new Exception(string.Join("\n", errors.Select(e => e.ToString()).ToArray())); } //bool statusChanged = false; if (existingCondo != null) { existingCondo.OfficialName = condo.OfficialName; existingCondo.Address = condo.Address; existingCondo.Postcode = condo.Postcode; existingCondo.Town = condo.Town; existingCondo.BuildingsType = condo.BuildingsType; existingCondo.BuildingsNumber = condo.BuildingsNumber; existingCondo.StaircasesNumber = condo.StaircasesNumber; existingCondo.BuildingYear = condo.BuildingYear; existingCondo.LastUpdated = condo.LastUpdated; //statusChanged = (existingCondo.Deactivated != condo.Deactivated); existingCondo.Deactivated = condo.Deactivated; // for existing Condo it is not necessary to call ISession.SaveOrUpdate() because it is // already attached to the session. See http://stackoverflow.com/questions/1380581/nhibernate-commit-db-changes-without-explict-call-to-save-or-update condo = existingCondo; } condoRepository.Save(condo); // if (statusChanged) // { // this.sendEmailStatusChanged(condo, // Core.Common.Constants.TemplateParams.CONDO, // Core.Common.Constants.SettingsKeys.KEY_EMAIL_CONDO_STATUS_CHANGED_SUBJECT, // Core.Common.Constants.SettingsKeys.KEY_EMAIL_CONDO_STATUS_CHANGED_BODY_TEMPLATE); // } } public void SaveBoardMemberInformation(Taloyhtio.GeneralApi.Common.DTO.BoardMember b) { var securityContext = this.ensureAuthorized(); if (b == null) { throw new ArgumentNullException("boardMember"); } // current assumption is that business id is login name //string businessIdPMC = HttpContext.Current.User.Identity.Name; string businessIdPMC = securityContext.PrimaryIdentity.Name; var boardMembersRepository = ServiceLocator.Current.GetInstance(); var existingBoardMember = boardMembersRepository.GetBy(b.FirstName, b.LastName, b.CondoName); if (existingBoardMember != null) { // pmc may update only board members of their own condos if (existingBoardMember.Condo.BusinessIdPMC != businessIdPMC) { throw new WebException(HttpStatusCode.Unauthorized, string.Format(TaloyhtioIntegration_resx.SecurityIncorrectBusinessIdPMC, businessIdPMC, existingBoardMember.Condo.BusinessId)); } } // construct board member entity from dto object for validation and saving var mapper = ServiceLocator.Current.GetInstance>(); var boardMember = mapper.Map(b); boardMember.LastUpdated = DateTime.Now; if (existingBoardMember != null) { boardMember.Condo = existingBoardMember.Condo; } else { var condoRepository = ServiceLocator.Current.GetInstance(); boardMember.Condo = condoRepository.GetByOfficialName(b.CondoName); } var validator = ServiceLocator.Current.GetInstance(); var errors = validator.Validate(boardMember); if (!errors.IsNullOrEmpty()) { throw new Exception(string.Join("\n", errors.Select(e => e.ToString()).ToArray())); } bool statusChanged = false; bool newBoardMember = existingBoardMember == null; if (existingBoardMember != null) { existingBoardMember.Address = boardMember.Address; existingBoardMember.Postcode = boardMember.Postcode; existingBoardMember.Town = boardMember.Town; existingBoardMember.FlatNumber = boardMember.FlatNumber; existingBoardMember.Email = boardMember.Email; existingBoardMember.Mobile = boardMember.Mobile; existingBoardMember.LastUpdated = boardMember.LastUpdated; statusChanged = (existingBoardMember.Deactivated != boardMember.Deactivated); existingBoardMember.Deactivated = boardMember.Deactivated; // for existing Condo it is not necessary to call ISession.SaveOrUpdate() because it is // already attached to the session. See http://stackoverflow.com/questions/1380581/nhibernate-commit-db-changes-without-explict-call-to-save-or-update boardMember = existingBoardMember; } boardMembersRepository.Save(boardMember); if (newBoardMember) { this.sendEmailStatusChanged(boardMember, Taloyhtio.GeneralApi.Core.Common.Constants.TemplateParams.BOARD_MEMBER, Taloyhtio.GeneralApi.Core.Common.Constants.SettingsKeys.KEY_EMAIL_BOARD_MEMBER_NEW_SUBJECT, Taloyhtio.GeneralApi.Core.Common.Constants.SettingsKeys.KEY_EMAIL_BOARD_MEMBER_NEW_BODY_TEMPLATE); } else if (statusChanged) { this.sendEmailStatusChanged(boardMember, Taloyhtio.GeneralApi.Core.Common.Constants.TemplateParams.BOARD_MEMBER, Taloyhtio.GeneralApi.Core.Common.Constants.SettingsKeys.KEY_EMAIL_BOARD_MEMBER_STATUS_CHANGED_SUBJECT, Taloyhtio.GeneralApi.Core.Common.Constants.SettingsKeys.KEY_EMAIL_BOARD_MEMBER_STATUS_CHANGED_BODY_TEMPLATE); } } private void sendEmailStatusChanged(T item, string templateParam, string subjKey, string bodyTemplateKey) { try { var settingsProvider = ServiceLocator.Current.GetInstance(); string to = settingsProvider.Get(Taloyhtio.GeneralApi.Core.Common.Constants.SettingsKeys.KEY_EMAIL_TO); string subj = settingsProvider.Get(subjKey); string bodyTemplate = settingsProvider.Get(bodyTemplateKey); var templateEngine = ServiceLocator.Current.GetInstance(); //var propertyExtractor = ServiceLocator.Current.GetInstance(); string body = templateEngine.Merge(bodyTemplate, new Pair(templateParam, item)); body = body.Replace("\\n", "\n"); var emailService = ServiceLocator.Current.GetInstance(); emailService.Send(to, subj, body); } catch (Exception x) { var logger = ServiceLocator.Current.GetInstance(); logger.LogError("sendEmailCondoStatusChanged:\n{0}\n{1}", x.Message, x.StackTrace); } } private ServiceSecurityContext ensureAuthorized() { var securityContext = OperationContext.Current.ServiceSecurityContext; if (securityContext == null || securityContext.IsAnonymous) { throw new WebException(HttpStatusCode.Unauthorized, TaloyhtioIntegration_resx.SecurityNotAuthorized); } return securityContext; } } }