I've hacked the following code together to get some details from my users' profile data. It works, but isn't pretty.
I have a UserPreferences
object that is saved in the users' profiles. It has properties for whether SMS alert messages are desired and for which alert types. The SMS will be sent as an email. When an alert is created, I want to get a comma-delimited string of the addresses that should get notified for that alert type.
The user has a mobile number and a carrier. The carriers have an SMS email format like "{number}@ {domain}
and I'm replacing those fields with the user's number and the carrier's domain.
As I said, this does work, but I don't care for it being two methods or how messy it seems. Is there a more compact way of writing this as one method?
public static string GetSMSAlertSubscribers(int alertTypeId) {
// end result I want is like: "1234567890@vtext.com,0987654321@text.att.net"
return String.Join(",", GetSMSAlertSubscribersEnumerable(alertTypeId));
}
public static IEnumerable<string> GetSMSAlertSubscribersEnumerable(int alertTypeId) {
var prefs = Membership.GetAllUsers()
.Cast<MembershipUser>()
.Where(u => WebProfile.GetProfile(u.UserName).Preferences.SendAlertsToSMS.Equals(true)
&& WebProfile.GetProfile(u.UserName).Preferences.SMSAlertTypeIds.Contains(alertTypeId))
.Select(u => WebProfile.GetProfile(u.UserName).Preferences);
var carriers = new AlertRepository().FindAllMobileCarriers().ToList();
foreach (UserPreferences p in prefs) {
yield return carriers.Where(c => c.Id.Equals(p.MobileCarrierId))
.Select(c => c.SMSEmailAddressFormat.Replace("{domain}", c.SMSEmailAddressDomain).Replace("{number}", p.MobileNumber))
.SingleOrDefault();
}
}
I'd call it like:
var emailTo = GetSMSAlertSubscribers(3);
UPDATE: I've refactored my "prefs" query to reduce the repetitive use of GetProfile()
as:
var prefs = Membership.GetAllUsers()
.OfType<MembershipUser>()
.Select(u => WebProfile.GetProfile(u.UserName).Preferences)
.Where(p => p.SendAlertsToSMS && p.SMSAlertTypeIds.Contains(alertTypeId));