public Task <IList <SubmittersContactDetail> > GetSuperSubmittersAsync() { using (var db = new WebGalleryDbContext()) { var submitters = (from c in db.SubmittersContactDetails join s in db.Submitters on c.SubmitterID equals s.SubmitterID where s.IsSuperSubmitter.HasValue && s.IsSuperSubmitter == true select new { SubmitterID = s.SubmitterID, MicrosoftAccount = s.MicrosoftAccount, Prefix = c.Prefix, Suffix = c.Suffix, FirstName = c.FirstName, MiddleName = c.MiddleName, LastName = c.LastName }).AsEnumerable(); return(Task.FromResult <IList <SubmittersContactDetail> >((from s in submitters select new SubmittersContactDetail { SubmitterID = s.SubmitterID, EMail = s.MicrosoftAccount, Prefix = s.Prefix, Suffix = s.Suffix, FirstName = s.FirstName, MiddleName = s.MiddleName, LastName = s.LastName }).ToList())); } }
public Task CreateAsync(Submitter invitee, Submission submission, UnconfirmedSubmissionOwner invitation) { using (var db = new WebGalleryDbContext()) { // remove invitation db.UnconfirmedSubmissionOwners.RemoveRange(from u in db.UnconfirmedSubmissionOwners where u.RequestID == invitation.RequestID select u); // if the invitee has no ownership for this app, add one var alreadyHasOwnership = db.SubmissionOwners.Any(o => o.SubmissionID == submission.SubmissionID && o.SubmitterID == invitee.SubmitterID); if (!alreadyHasOwnership) { db.SubmissionOwners.Add(new SubmissionOwner { SubmissionID = submission.SubmissionID, SubmitterID = invitee.SubmitterID }); } db.SaveChanges(); return(Task.FromResult(0)); } }
public Task RemoveInvitationAsync(Guid invitationGuid) { using (var db = new WebGalleryDbContext()) { db.UnconfirmedSubmissionOwners.RemoveRange(from u in db.UnconfirmedSubmissionOwners where u.RequestID == invitationGuid select u); db.SaveChanges(); return(Task.FromResult(0)); } }
public Task <bool> IsOwnerAsync(int submitterId, int submissionId) { using (var db = new WebGalleryDbContext()) { var isOwner = (from s in db.SubmissionOwners where s.SubmitterID == submitterId && s.SubmissionID == submissionId select s.SubmissionOwnerID).Any(); return(Task.FromResult(isOwner)); } }
public Task <bool> HasContactInfoAsync(int submitterId) { using (var db = new WebGalleryDbContext()) { var hasOrNot = (from c in db.SubmittersContactDetails where c.SubmitterID == submitterId select c).Any(); return(Task.FromResult(hasOrNot)); } }
public Task <UnconfirmedSubmissionOwner> GetInvitationAsync(Guid invitationGuid) { using (var db = new WebGalleryDbContext()) { var invitation = (from u in db.UnconfirmedSubmissionOwners where u.RequestID == invitationGuid select u).FirstOrDefault(); return(Task.FromResult(invitation)); } }
public Task <Submitter> GetSubmitterAsync(int submitterId) { using (var db = new WebGalleryDbContext()) { var submitter = (from s in db.Submitters where s.SubmitterID == submitterId select s).FirstOrDefault(); return(Task.FromResult(submitter)); } }
public Task <SubmittersContactDetail> GetContactDetailAsync(int submitterId) { using (var db = new WebGalleryDbContext()) { var detail = (from d in db.SubmittersContactDetails where d.SubmitterID == submitterId select d).FirstOrDefault(); return(Task.FromResult(detail)); } }
public Task <Submitter> GetSubmitterByMicrosoftAccountAsync(string submitterMicrosoftAccount) { using (var db = new WebGalleryDbContext()) { var submitter = (from s in db.Submitters where s.MicrosoftAccount.Equals(submitterMicrosoftAccount, StringComparison.OrdinalIgnoreCase) select s).FirstOrDefault(); return(Task.FromResult(submitter)); } }
public Task RemoveAsync(int submitterId, int submissionId) { using (var db = new WebGalleryDbContext()) { db.SubmissionOwners.RemoveRange(from o in db.SubmissionOwners where o.SubmissionID == submissionId && o.SubmitterID == submitterId select o); db.SaveChanges(); return(Task.FromResult(0)); } }
public Task <bool> HasBeenInvitedAsync(string firstName, string lastName, Submission submission) { using (var db = new WebGalleryDbContext()) { var invitationQuery = from i in db.UnconfirmedSubmissionOwners where i.FirstName.Equals(firstName, StringComparison.OrdinalIgnoreCase) && i.LastName.Equals(lastName, StringComparison.OrdinalIgnoreCase) && i.IsSuperSubmitterRequest == false && i.SubmissionID == submission.SubmissionID select i; return(Task.FromResult(invitationQuery.Any())); } }
public Task <bool> HasOwnershipAsync(string firstName, string lastName, Submission submission) { using (var db = new WebGalleryDbContext()) { var ownerQuery = from o in db.SubmissionOwners join c in db.SubmittersContactDetails on o.SubmitterID equals c.SubmitterID where o.SubmissionID == submission.SubmissionID && c.FirstName.Equals(firstName, StringComparison.OrdinalIgnoreCase) && c.LastName.Equals(lastName, StringComparison.OrdinalIgnoreCase) select o; return(Task.FromResult(ownerQuery.Any())); } }
public Task SendOwnershipInvitation(string emailAddressOfInvitee, UnconfirmedSubmissionOwner unconfirmedSubmissionOwner, string urlAuthority, Func <string, string> htmlEncode) { using (var db = new WebGalleryDbContext()) { var submission = (from s in db.Submissions where s.SubmissionID == unconfirmedSubmissionOwner.SubmissionID select s).FirstOrDefault(); if (submission == null) { return(Task.FromResult(0)); } // html encode some strings submission.Nickname = htmlEncode(submission.Nickname); submission.Version = htmlEncode(submission.Version); unconfirmedSubmissionOwner.FirstName = htmlEncode(unconfirmedSubmissionOwner.FirstName); unconfirmedSubmissionOwner.LastName = htmlEncode(unconfirmedSubmissionOwner.LastName); var invitationGuid = htmlEncode(unconfirmedSubmissionOwner.RequestID.ToString()); // build the body of the email var bodyBuilder = new StringBuilder(); bodyBuilder.Append($"<p>{unconfirmedSubmissionOwner.FirstName} {unconfirmedSubmissionOwner.LastName}:</p>"); bodyBuilder.Append($"<p>You have been invited to take co-ownership of an application intended for inclusion in Microsoft's <a href='https://{urlAuthority}' title='Web App Gallery'>Web App Gallery</a>.</p>"); bodyBuilder.Append("<p>"); bodyBuilder.Append($"The ID of the application is {submission.Nickname}.<br />"); bodyBuilder.Append($"The version is {submission.Version}."); bodyBuilder.Append("</p>"); bodyBuilder.Append("<p>"); bodyBuilder.Append($"To accept this invitation please visit <a href='https://{urlAuthority}/ownership/invitations/{invitationGuid}' title='go here to accept this invitation'>this Web page</a> and follow these steps:"); bodyBuilder.Append("</p>"); bodyBuilder.Append("<ol>"); bodyBuilder.Append("<li>Log into Live ID. If you do not yet have a Live ID account you will be able to create one from the log-in page.</li>"); bodyBuilder.Append("<li>Provide us with your contact information (unless you have done so in the past).</li>"); bodyBuilder.Append("<li>Click the appropriate button to accept or decline this invitation.</li>"); bodyBuilder.Append("</ol>"); bodyBuilder.Append("<p>"); bodyBuilder.Append("Best regards,<br />"); bodyBuilder.Append("Web Application Gallery Team"); bodyBuilder.Append("</p>"); var subject = "You are invited to be a co-owner of an Web App Gallery application"; var from = GetFromMailAddress(); SendGridEmailHelper.SendAsync(subject, bodyBuilder.ToString(), from.Address, from.DisplayName, emailAddressOfInvitee); return(Task.FromResult(0)); } }
public Task AddSuperSubmitterAsync(string microsoftAccount, string firstName, string lastName) { using (var db = new WebGalleryDbContext()) { var submitter = (from s in db.Submitters where s.MicrosoftAccount.Equals(microsoftAccount, StringComparison.OrdinalIgnoreCase) select s).FirstOrDefault(); // If the super submitter to be added hasn't had a submittership yet, add a new one first in the Submitters table. if (submitter == null) { submitter = new Submitter { MicrosoftAccount = microsoftAccount, PersonalID = string.Empty, PersonalIDType = 1, IsSuperSubmitter = true }; db.Submitters.Add(submitter); db.SaveChanges(); // save to database for new submitter id. } else { submitter.IsSuperSubmitter = true; } // For a new super submitter who has no record in table SubmitterContactDetails, // make a new one with the parameters firstName and lastName. // If the super submitter already has contact details in the table SubmittersContactDetails, we do nothing here. var contactDetail = (from c in db.SubmittersContactDetails where c.SubmitterID == submitter.SubmitterID select c).FirstOrDefault(); if (contactDetail == null) { contactDetail = new SubmittersContactDetail { SubmitterID = submitter.SubmitterID, FirstName = firstName, LastName = lastName }; db.SubmittersContactDetails.Add(contactDetail); } db.SaveChanges(); return(Task.FromResult(0)); } }
public Task RemoveSuperSubmitterAsync(int submitterId) { using (var db = new WebGalleryDbContext()) { var submitter = (from s in db.Submitters where s.SubmitterID == submitterId select s).FirstOrDefault(); if (submitter != null) { submitter.IsSuperSubmitter = false; db.SaveChanges(); } return(Task.FromResult(0)); } }
private static void UpdateFileSizeForPackage(string packageUrl, int fileSize, int submissionId) { using (var db = new WebGalleryDbContext()) { var packages = (from p in db.Packages where p.SubmissionID == submissionId select p).ToList(); foreach (var p in packages.Where(p => p.PackageURL == packageUrl)) { p.FileSize = fileSize; } db.SaveChanges(); } }
public Task UpdateMsaAsync(int submitterId, string microsoftAccount) { using (var db = new WebGalleryDbContext()) { var submitter = (from s in db.Submitters where s.SubmitterID == submitterId select s).FirstOrDefault(); if (submitter != null) { submitter.MicrosoftAccount = microsoftAccount; } db.SaveChanges(); return(Task.FromResult(0)); } }
public Task <UnconfirmedSubmissionOwner> CreateInvitationAsync(string firstName, string lastName, Submission submission) { using (var db = new WebGalleryDbContext()) { var unconfirmedSubmissionOwner = new UnconfirmedSubmissionOwner { SubmissionID = submission.SubmissionID, RequestID = Guid.NewGuid(), RequestDate = DateTime.Now, FirstName = firstName, LastName = lastName, IsSuperSubmitterRequest = false }; db.UnconfirmedSubmissionOwners.Add(unconfirmedSubmissionOwner); db.SaveChanges(); return(Task.FromResult(unconfirmedSubmissionOwner)); } }
public Task <Issue> SaveAsync(IssueType issueType, string appId, string issueDescription, string reporterFirstName, string reporterLastName, string reporterEmail) { using (var db = new WebGalleryDbContext()) { var issue = new Issue { IssueType = (int)issueType, AppId = appId, IssueDescription = issueDescription, ReporterFirstName = reporterFirstName, ReporterLastName = reporterLastName, ReporterEmail = reporterEmail, DateReported = DateTime.Now }; db.Issues.Add(issue); db.SaveChanges(); return(Task.FromResult(issue)); } }
public Task <Submitter> SaveContactDetailAsync(string email, SubmittersContactDetail contactDetail) { using (var db = new WebGalleryDbContext()) { var submitter = (from s in db.Submitters where s.MicrosoftAccount.Equals(email, StringComparison.OrdinalIgnoreCase) select s).FirstOrDefault(); if (submitter == null) { submitter = new Submitter { MicrosoftAccount = email, PersonalID = string.Empty, PersonalIDType = 1, IsSuperSubmitter = null }; db.Submitters.Add(submitter); db.SaveChanges(); // save to database for new submitter id. } var contactDetailInDb = (from c in db.SubmittersContactDetails where c.SubmitterID == submitter.SubmitterID select c).FirstOrDefault(); if (contactDetailInDb == null) { contactDetail.SubmitterID = submitter.SubmitterID; db.SubmittersContactDetails.Add(contactDetail); } else { SyncContactDetailProperties(contactDetailInDb, contactDetail); } db.SaveChanges(); return(Task.FromResult(submitter)); } }
public Task <IList <SubmittersContactDetail> > GetSubmittersAsync(string keyword, int page, int pageSize, out int count) { using (var db = new WebGalleryDbContext()) { var query = from s in db.Submitters join c in db.SubmittersContactDetails on s.SubmitterID equals c.SubmitterID join o in db.SubmissionOwners on s.SubmitterID equals o.SubmitterID into ships where keyword == null || keyword.Trim() == string.Empty || (c.FirstName + " " + c.LastName).ToLower().Contains(keyword.Trim().ToLower()) || s.PersonalID.Equals(keyword.Trim(), StringComparison.OrdinalIgnoreCase) orderby ships.Count() descending select new { SubmitterId = s.SubmitterID, Prefix = c.Prefix, Suffix = c.Suffix, FirstName = c.FirstName, LastName = c.LastName, SubmissionAmount = ships.Count(), PUID = s.PersonalID, MicrosoftAccount = s.MicrosoftAccount }; count = query.Count(); var submitters = query.Skip((page - 1) * pageSize).Take(pageSize).AsEnumerable(); return(Task.FromResult <IList <SubmittersContactDetail> >(submitters.Select(s => new SubmittersContactDetail { SubmitterID = s.SubmitterId, Prefix = s.Prefix, Suffix = s.Suffix, FirstName = s.FirstName, LastName = s.LastName, SubmissionAmount = s.SubmissionAmount, PUID = s.PUID, EMail = s.MicrosoftAccount }).ToList())); } }
public Task SendMessageForIssueReported(Issue issue, Func <string, string> htmlEncode) { // html encode user inputs issue.ReporterFirstName = htmlEncode(issue.ReporterFirstName); issue.ReporterLastName = htmlEncode(issue.ReporterLastName); issue.IssueDescription = htmlEncode(issue.IssueDescription); var subject = $"Ticket #{issue.IssueID} [{Enum.GetName(typeof(IssueType), issue.IssueType)}]"; var from = GetFromMailAddress(); // set the table's style var style = @" <style> table tr { margin: 0; padding: 0; } table tr th, table tr td { padding: 2px; margin: 0; border: solid 1px #666666; text-align: left; font-family: Segoe UI, Verdana, Tahoma, Helvetica, Arial, sans-serif; font-size: 12px; line-height: 1.2em; } </style> "; // first, send email to the user who reported the issue var messageBodyToUser = new StringBuilder(); messageBodyToUser.Append($"<p>Hello {issue.ReporterFirstName} {issue.ReporterLastName}</p>"); // the type of app issue is 2 if (issue.IssueType == 2) { messageBodyToUser.Append(style); messageBodyToUser.Append("<p>Please share the following details to help resolve the issue.</p>"); messageBodyToUser.Append("<ol><li>Share the logs in %localappdata%\\microsoft\\Web Platform Installer\\logs folder</li>"); messageBodyToUser.Append("<li>Screenshots on the error</li>"); messageBodyToUser.Append("<li>Steps to reproduce the error</li></ol>"); messageBodyToUser.Append("<p>Here is the expected response time to address your issue.</p>"); messageBodyToUser.Append("<p><table cellpadding='0' cellspacing='0'>"); messageBodyToUser.Append("<tr><th>Issue Type</th><th>Response time Service level agreement (SLA)</th></tr>"); messageBodyToUser.Append("<tr><td>Submission portal issue</td><td>1-3 days</td></tr>"); messageBodyToUser.Append("<tr><td>Application Issue</td><td>The application owner will get back to you on the issue. </td></tr>"); messageBodyToUser.Append("</table></p>"); } else { messageBodyToUser.Append("<p>Thank you for contacting Web App Gallery team! Your request has been received, and is being reviewed by our team. If you haven’t already, please check out our <a href='http://www.iis.net/learn/develop/windows-web-application-gallery'>documentation</a> or our <a href='http://www.iis.net/learn/develop/windows-web-application-gallery/frequently-asked-questions'>FAQ</a> where you can find answers to the most common questions.</p>"); messageBodyToUser.Append("<p>Please expect a response from us in 3-5 business days</p>"); } messageBodyToUser.Append("<p>Thanks</p>"); messageBodyToUser.Append("<p>App Gallery Team</p>"); SendGridEmailHelper.SendAsync(subject, messageBodyToUser.ToString(), from.Address, from.DisplayName, issue.ReporterEmail); // second, send email to Microsoft and/or the app owners var messageBodyToMicrosoftOrOwners = new StringBuilder(); messageBodyToMicrosoftOrOwners.Append("<p>Hello</p>"); messageBodyToMicrosoftOrOwners.Append($"<p>An issue was reported by <a href='mailto:{issue.ReporterEmail}'>{issue.ReporterFirstName} {issue.ReporterLastName}</a>.</p>"); messageBodyToMicrosoftOrOwners.Append("<p><table cellpadding='0' cellspacing='0'>"); var appIdStatement = string.IsNullOrWhiteSpace(issue.AppId) ? string.Empty : $" for the app: {issue.AppId}"; messageBodyToMicrosoftOrOwners.Append($"<tr><th>Issue Category</th><td>{Enum.GetName(typeof(IssueType), issue.IssueType)}{appIdStatement}</td></tr>"); messageBodyToMicrosoftOrOwners.Append($"<tr><th>Issue Details</th><td>{issue.IssueDescription}</td></tr>"); messageBodyToMicrosoftOrOwners.Append("</table></p>"); messageBodyToMicrosoftOrOwners.Append("<p>Thanks</p>"); messageBodyToMicrosoftOrOwners.Append("<p>App Gallery Team</p>"); // get the email addresses of the owners of the app in this issue var emailAddressesOfOwners = string.Empty; using (var db = new WebGalleryDbContext()) { var addresses = (from s in db.Submissions join o in db.SubmissionOwners on s.SubmissionID equals o.SubmissionID join c in db.Submitters on o.SubmitterID equals c.SubmitterID // If App Issue , send the above email to appgal team and application owner email in submitters table . where s.Nickname == issue.AppId select c.MicrosoftAccount).AsEnumerable(); emailAddressesOfOwners = string.Join(",", addresses); } if (string.IsNullOrWhiteSpace(emailAddressesOfOwners)) { // if found no email addresses of owners, then send to only Microsoft var to = from.Address; SendGridEmailHelper.SendAsync(subject, style + messageBodyToMicrosoftOrOwners.ToString(), from.Address, from.DisplayName, to); } else { // or send to the owners and cc to Microsoft var cc = from.Address; SendGridEmailHelper.SendAsync(subject, style + messageBodyToMicrosoftOrOwners.ToString(), from.Address, from.DisplayName, emailAddressesOfOwners, cc); } return(Task.FromResult(0)); }
public void SendMessageForSubmission(Submitter submitter, Submission submission, string action, string urlAuthority, Func <string, string> htmlEncode) { if (submitter == null || submission == null) { return; } using (var db = new WebGalleryDbContext()) { var contactInfo = (from c in db.SubmittersContactDetails where c.SubmitterID == submitter.SubmitterID select c).FirstOrDefault(); var metadata = (from m in db.SubmissionLocalizedMetaDatas where m.SubmissionID == submission.SubmissionID select m).ToList(); var packages = (from p in db.Packages where p.SubmissionID == submission.SubmissionID select p).ToList(); var frameworkName = (from f in db.FrameworksAndRuntimes where f.FrameworkOrRuntimeID == submission.FrameworkOrRuntimeID select f.Name).FirstOrDefault(); var categoryName1 = (from c in db.ProductOrAppCategories where c.CategoryID.ToString() == submission.CategoryID1 select c.Name).FirstOrDefault(); var categoryName2 = (from c in db.ProductOrAppCategories where c.CategoryID.ToString() == submission.CategoryID2 select c.Name).FirstOrDefault(); var owners = (from o in db.SubmissionOwners join d in db.SubmittersContactDetails on o.SubmitterID equals d.SubmitterID where o.SubmissionID == submission.SubmissionID select d).ToList(); // html encode some fields submission.Version = htmlEncode(submission.Version); submission.SubmittingEntity = htmlEncode(submission.SubmittingEntity); submission.AdditionalInfo = htmlEncode(submission.AdditionalInfo); foreach (var m in metadata) { m.Name = htmlEncode(m.Name); m.Description = htmlEncode(m.Description); m.BriefDescription = htmlEncode(m.BriefDescription); } foreach (var p in packages) { p.StartPage = htmlEncode(p.StartPage); p.SHA1Hash = htmlEncode(p.SHA1Hash); } // build subject and body var subject = BuildSubject(submission, action); var body = BuildBody(submitter, contactInfo, submission, categoryName1, categoryName2, frameworkName, metadata, packages, action, urlAuthority); body += "Submission:<br/>"; // create a new anonymous object for serialization // to avoid the error "The ObjectContext instance has been disposed ..." var submissionJson = new { SubmissionID = submission.SubmissionID, Nickname = submission.Nickname, Version = submission.Version, SubmittingEntity = submission.SubmittingEntity, SubmittingEntityURL = submission.SubmittingEntityURL, AppURL = submission.AppURL, SupportURL = submission.SupportURL, ReleaseDate = submission.ReleaseDate, ProfessionalServicesURL = submission.ProfessionalServicesURL, CommercialProductURL = submission.CommercialProductURL, CategoryID1 = submission.CategoryID1, CategoryID2 = submission.CategoryID2, LogoUrl = submission.LogoUrl, ScreenshotUrl1 = submission.ScreenshotUrl1, ScreenshotUrl2 = submission.ScreenshotUrl2, ScreenshotUrl3 = submission.ScreenshotUrl3, ScreenshotUrl4 = submission.ScreenshotUrl4, ScreenshotUrl5 = submission.ScreenshotUrl5, ScreenshotUrl6 = submission.ScreenshotUrl6, FrameworkOrRuntimeID = submission.FrameworkOrRuntimeID, DatabaseServerIDs = submission.DatabaseServerIDs, WebServerExtensionIDs = submission.WebServerExtensionIDs, AgreedToTerms = submission.AgreedToTerms, AdditionalInfo = submission.AdditionalInfo, Created = submission.Created, Updated = submission.Updated, }; body += JsonConvert.SerializeObject(submissionJson, Formatting.Indented).Replace(" ", " ").Replace("\r\n", "<br/>"); body += "<hr/><br/><br/>Submission Metadata:<br/>"; body += JsonConvert.SerializeObject(metadata, Formatting.Indented).Replace(" ", " ").Replace("\r\n", "<br/>"); // get the from email address var from = GetFromMailAddress(); // First send email internally (to folks at MS). var to = from.Address; SendGridEmailHelper.SendAsync(subject, BuildHtmlStyles() + body, from.Address, from.DisplayName, to); // Second, send email externally (to the app owners). Here, we don't include the XML. foreach (var owner in owners) { var note = string.Empty; switch (action) { case "VERIFIED": note = BuildSubmissionNote(htmlEncode(owner.FullName), from.Address, submission.Nickname, submission.Version, urlAuthority); break; case "PUBLISHED": note = BuildPublishNote(htmlEncode(owner.FullName), submission.Nickname, submission.Version, urlAuthority); break; default: break; } to = owner.EMail; body = note + BuildBody(submitter, contactInfo, submission, categoryName1, categoryName2, frameworkName, metadata, packages, action, urlAuthority); SendGridEmailHelper.SendAsync(subject, BuildHtmlStyles() + body, from.Address, from.DisplayName, to); } } }
public Task <List <AppValidationItem> > GetValidationItemsAsync(Submission submission) { var urlItems = new List <AppValidationItem> { new AppValidationItem { Type = AppValidationItemType.Url, Name = "SubmittingEntityUrl", Value = submission.SubmittingEntityURL }, new AppValidationItem { Type = AppValidationItemType.Url, Name = "AppWebSiteUrl", Value = submission.AppURL }, new AppValidationItem { Type = AppValidationItemType.Url, Name = "SupportUrl", Value = submission.SupportURL }, new AppValidationItem { Type = AppValidationItemType.Url, Name = "ProfessionalServicesUrl", Value = submission.ProfessionalServicesURL }, new AppValidationItem { Type = AppValidationItemType.Url, Name = "CommercialProductUrl", Value = submission.CommercialProductURL }, }; var imageItems = new List <AppValidationItem> { new AppValidationItem { Type = AppValidationItemType.Image, Name = "LogoType", Value = submission.LogoUrl }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "LogoDimensions", Value = submission.LogoUrl }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot1Type", Value = submission.ScreenshotUrl1 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot1Dimensions", Value = submission.ScreenshotUrl1 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot2Type", Value = submission.ScreenshotUrl2 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot2Dimensions", Value = submission.ScreenshotUrl2 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot3Type", Value = submission.ScreenshotUrl3 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot3Dimensions", Value = submission.ScreenshotUrl3 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot4Type", Value = submission.ScreenshotUrl4 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot4Dimensions", Value = submission.ScreenshotUrl4 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot5Type", Value = submission.ScreenshotUrl5 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot5Dimensions", Value = submission.ScreenshotUrl5 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot6Type", Value = submission.ScreenshotUrl6 }, new AppValidationItem { Type = AppValidationItemType.Image, Name = "Screenshot6Dimensions", Value = submission.ScreenshotUrl6 }, }; IEnumerable <Package> packages = null; using (var db = new WebGalleryDbContext()) { packages = (from p in db.Packages where p.SubmissionID == submission.SubmissionID select p).ToList(); } // sort on a in-memory collection, that way will speed somehow packages = packages.OrderByDescending(p => p.PackageID); var packageValidationItems = new List <AppValidationItem>(); foreach (var lang in Language.SupportedLanguages) { var package = packages.FirstOrDefault(p => p.Language == lang.Name); if (package != null) { packageValidationItems.Add(new AppValidationItem { Name = package.PackageURL, Type = AppValidationItemType.Package, LanguageAndCountryCode = lang.Name, Value = package.SHA1Hash }); } } return(Task.FromResult( urlItems .Union(imageItems) .Union(packageValidationItems) .ToList())); }