I want to extract the addresses OUT OF MailGun, into a CSV and delete the MailGun altogether.
The MailGun database is the only copy of the 951 addresses I have absolutely no access to the database in any form other than looking at the list in MailGun.
http://documentation.mailgun.com/api-mailinglists.html#mailing-lists
This is my solution to this problem in C# ,and it can get all members of a list(not only 100 limited).In addition, i use Newtonsoft.Json. Update: I found the 'total_count' has a maximum value 10000, so if the members in your mailing list is more than 10000, the request will return the maximum value 10000! In that case, this is not a great solution!
public void ExportMailList(string listName)
{
RestClient client = new RestClient();
List<MemberDetail> totalMember = new List<MemberDetail>();
client.BaseUrl = new Uri("https://api.mailgun.net/v3");
client.Authenticator =
new HttpBasicAuthenticator("api",
"key-yourKey");
RestRequest reqForTotal = new RestRequest();
reqForTotal.Resource = "lists/{list}/members";
reqForTotal.AddParameter("list", listName, ParameterType.UrlSegment);
int resultTotal= JsonConvert.DeserializeObject<Member>(client.Execute(reqForTotal).Content).total_count;
int skipTimes = resultTotal / 100;
for (int i = 0; i <= skipTimes; i++)
{
RestRequest request = new RestRequest();
request.Resource = "lists/{list}/members";
request.AddParameter("list", listName, ParameterType.UrlSegment);
request.AddParameter("skip",100*i);
totalMember.AddRange(JsonConvert.DeserializeObject<Member>(client.Execute(request).Content).items);
}
//CreateCSVFromGenericList(...);
}
public class Member
{
public List<MemberDetail> items { get; set; }
public int total_count { get; set; }
}
public class MemberDetail
{
public string address { get; set; }
public string name { get; set; }
public bool subscribed { get; set; }
public object vars { get; set; }
}
In the method CreateCSVFromGenericList(..), you can refer to this blog, and export the data to .csv file in any format you want.
Using curl,php or any other programming language you can achieve this, then simply delete the mailing list through the control panel:
curl -s --user 'api:YOURAPIKEY' -G \
https://api.mailgun.net/v2/lists/Your#MailingListName.com/members
Apikey and mailing list name are available from the control panel!
In python :
def get_members():
return requests.get(
"https://api.mailgun.net/v3/lists/LIST_NAME/members",
auth=("api", "key-YOUR_KEY"),
data={'limit': 100, 'skip': 1380})
Note that limit and skip are useful to paginate through your member list.
Related
After changing the mapping to Automapper, only an empty list is sent through the endpoint.
Initially I had an endpoint that retrieved all employees with info including a list with every course each employee had taken. This was with manual mapping between entities & Dto.
//From startup.cs in Configure
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Employee, Models.EmployeeCoursesDto>();
cfg.CreateMap<Employee, Models.EmployeeDto>();
cfg.CreateMap<EmployeeCourses, Models.EmployeeCoursesDto>();
});
//From Employee entity
public class Employee
{
[Key]
//Gen new Id key in DB when object created
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
[MaxLength(50)]
public string Title { get; set; }
public ICollection<EmployeeCourses> EmployeeCourses { get; set; }
= new List<EmployeeCourses>();
}
}
//From employee Dto
public class EmployeeDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public ICollection<EmployeeCoursesDto> EmployeeCourses { get; set; }
= new List<EmployeeCoursesDto>();
}
}
//Endpoint in controller
[HttpGet()]
public IActionResult GetAllEmployees()
{
var employeeEntities = _employeeInfoRepository.GetEmployees();
var results = Mapper.Map<IEnumerable<EmployeeDto>>(employeeEntities);
return Ok(results);
}
//From Irepository
IEnumerable<Employee> GetEmployees();
//From repository
public IEnumerable<Employee> GetEmployees()
{
return _context.Employees.OrderBy(c => c.Name).ToList();
}
I expected output all employees with all datafileds, including their list of courses.
The output is all fields with data, except the list of courses which is "0" when running with a breakpoint, and in Postman it shows as only:
"id": 2,
"name": "Test Person",
"title": "Bus Driver",
"numberOfCourses": 0,
"employeeCourses": [],
"totalAchievedHoursAuditor": 0,
"totalAchievedHoursAccountant": 51,
"courseBalanceAccountant": null,
"courseBalanceAuditor": null
However, if I try another endpoint only for retrieving a specific course, or a list of courses, the data show correctly. Seems there are an issue with mapping the employees & courses at the same time?
I found the error, not Automapper, but my Linq statement:
return _context.Employees.Include(c => c.EmployeeCourses).ToList();
Please close this thread. Thanks for the reply Lucian Bargaoanu & have a great weekend.
I have got response List<List<KeyValuePair<string, object>>> but I want to convert response into List<ClassName>.
KeyValuePair key and ClassName property both are same name and same type
What is the most programmatically way to convert response?
I have got response
My class structure
public class TestModel
{
public string TaxablePersonCode { get; set; }
public string LegalNameAsPerPan { get; set; }
public string TradeName { get; set; }
public string ConstitutionName { get; set; }
public string ResidentialStatusName { get; set; }
public string PrimaryMobileNo { get; set; }
public string FlatOrOfficeNo { get; set; }
public string TownOrCityOrDist { get; set; }
public string Pincode { get; set; }
public string StateName { get; set; }
public string CountryName { get; set; }
public string ContactName { get; set; }
public string ContactDesignationName { get; set; }
public string ContactMobile { get; set; }
public string ContactEmail { get; set; }
}
var listKeyValue = response.Select(x => x.Value).ToList();
var data = JsonConvert.DeserializeObject<List<TestModel>>(listKeyValue);
The only part of this im unsure about is when indexing the final list for the correct property, but you can choose what works best for you. Using a .Where() every time ensures you'll get the right result but it will search the list every single time and be a lot slower. If your %100 certain the order of the list will never change you could gain some performance by directly indexing the list for the element you want using [] or .ElementAt(). Anyway, heres what your looking for.
List<TestModel> myList = response.Select(x => new TestModel
{
// Using Where
TaxablePersonCode = x.Where(t => t.Key == "TaxablePersonCode").First().Value,
// Using direct index
LegalNameAsPerPan = x[1].Value,
// Using ElementAt
TradeName = x.ElementAt(2).Value,
...
});
Hope that helps!
Did you get some result with JsonConvert class? Did it worked for you? If not, you can try out something like this (if JSON and field are properly named):
var listKeyValue = response.Select(x => x.Value).ToList();
var result = new List<TestModel>();
foreach (var keyValueList in listKeyValue)
{
// convert the response list of KeyValuePair to dictionary
var dictionary = keyValueList.ToDictionary(kv => kv.Key, kv => kv.Value);
var tempModel = new TestModel();
// get actual value by name of the rpoperty
tempModel.TaxablePersonCode = dictionary[nameof(tempModel.TaxablePersonCode)].ToString();
// etc.
result.Add(tempModel);
}
Maybe this approach could be improved with reflection, but this will degrade the performance.
// get all properties to populate
var properties = typeof(TestModel).GetProperties(BindingFlags.Public | BindingFlags.Instance);
I see you're using JSON, so you should probably just deserialize the object properly, which I would expect to look something like this:
List<TestModel> models = JsonConvert.DeserializeObject<List<TestModel>>(response);
Otherwise, you could use reflection to bind the known KeyValuePair keys to the properties of the object; that being said, you will need to ensure that the return values are compatible with the values from the returned data, else this will fail.
outerList.ForEach(innerList => {
TestModel result = new TestModel();
innerList.ForEach(listItem => {
result
.GetType()
.GetProperty(listItem.Key)
?.SetValue(result, listItem.Value);
});
});
I have created a bunch of custom templates to store items (such as Industries, Subindustries, etc.) in Sitecore. I now want to go about loading these into my Sitecore MVC model.
The lists are located in sitecore > Content > Lists. For example inside the Lists folder there is a folder called Country. I want to get back all the items within the Country folder and populate them as unordered list in my view.
UPDATE: I implemented the Glass.Mapper.Sc method suggested below. It is fully operational now.
This is what my working model looks like now:
using Glass.Mapper.Sc.Configuration;
using Glass.Mapper.Sc.Configuration.Attributes;
using Sitecore.Data.Items;
using Sitecore.Mvc.Presentation;
using System;
using System.Collections.Generic;
namespace Sitecore.Web.Models
{
public class Registration: IRenderingModel
{
public Rendering Rendering { get; set; }
public Item Item { get; set; }
public Item PageItem { get; set; }
public IEnumerable<CountryChildItem> CountryList { get; set; }
[SitecoreType(AutoMap = true)]
public class CountryItem
{
public virtual IEnumerable<CountryChildItem> Children { get; set; }
}
[SitecoreType(AutoMap = true)]
public class CountryChildItem
{
[SitecoreId]
public virtual Guid Id { get; set; }
[SitecoreInfo(SitecoreInfoType.Path)]
public virtual string Path { get; set; }
[SitecoreField]
public virtual string DisplayName { get; set; }
[SitecoreField]
public virtual string Abbreviation { get; set; }
}
public void Initialize(Rendering rendering)
{
Rendering = rendering;
Item = rendering.Item;
PageItem = PageContext.Current.Item;
}
}
}
and this is what my working contoller looks like:
using Glass.Mapper.Sc;
using Sitecore.Web.Models;
using System.Web.Mvc;
namespace Sitecore.Web.Controllers
{
public class RegistrationController : Controller
{
Registration registrationModel = new Registration();
public ActionResult Index()
{
ISitecoreContext sitecoreContext = new SitecoreContext();
ISitecoreService service = new SitecoreService(sitecoreContext.Database);
Registration.CountryItem countryItem = service.GetItem<Registration.CountryItem>("/sitecore/content/Lists/Country");
registrationModel.CountryList = countryItem.Children;
return View(registrationModel);
}
}
}
and a snippet of my working view:
<ul class="select-menu-options dropdown-menu">
#foreach (var country in Model.CountryList)
{
<li>#country.DisplayName</li>
}
</ul>
If I were in your position I'd look into Glassmapper for Sitecore.
It's a fairly lightweight ORM for Sitecore.
http://www.glass.lu/Mapper/Sc
I'd also suggest moving the lists located in
sitecore > Templates > User Defined > Lists > Content
to some where under either
sitecore > Content
or
sitecore > System
(whichever makes more sence)
UPDATE:
Try adding this above your class:
[SitecoreType(AutoMap = true)]
public class CountryItem
{
//...
}
If you change your CountryItem and other model classes to inherit from SearchResultItem like that:
[PredefinedQuery("TemplateID", ComparisonType.Equal, "{ID-OF-CountryItem-TEMPLATE}", typeof(ID))]
public class CountryItem : Sitecore.ContentSearch.SearchTypes.SearchResultItem
{
[IndexField("_displayname")]
public virtual string DisplayName { get; set; }
[IndexField("abbreviation")]
public string Abbreviation { get; set; }
}
You should be able to use Sitecore indexes to retrieve all the countries and other lists like that:
private static string IndexName
{
get
{
return string.Format("sitecore_{0}_index", (Context.ContentDatabase ?? Context.Database).Name);
}
}
private static string Language { get { return Context.Language.Name; } }
public IEnumerable<CountryItem> GetCountries()
{
using (var context = ContentSearchManager.GetIndex(IndexName).CreateSearchContext())
{
IQueryable<CountryItem> queryable = context.GetQueryable<CountryItem>();
queryable = queryable.Where(i => i.Language == Language);
queryable = queryable.Where(i => i.LatestVersion);
// ... maybe excluding standard values or some other filters
var searchResults = queryable.GetResults();
return queryable.ToList();
}
}
Please be aware that this is just an example. You need to test it and most probably adapt to your solution.
And as Dar Brett mentioned, you should not keep any data items under the Templates node.
I've roughly followed this example but it doesnt solve my Sitecore-related redirect problem.
sitecore web form for marketers form post to external url
I've confirmed that my form POST works properly by using a 3rd party POST test tool. The problem I'm having is that in Sitecore they use a successMode to determine what the user wants todo if the submit is a success. If the user selects successmode/message, the form redirects back to a thank you message. If the user selects successmode/redirect, the success method pipeline looks for the success page value in the form and then a redirect happens to that URL. The problem with the redirect is that it loses my POST data.
Can anyone provide a Sitecore example of how they executed a form POST, and then redirect to the target external URL without losing POST values?
Did you use the successmode settings in the form?
I'm debating whether to overrride the successmode redirect pipeline, add conditions and test but I'm open to a solution that could include jquery.
Here's is my code:
using Sitecore.Data;
using Sitecore.Form.Core.Client.Data.Submit;
using Sitecore.Form.Core.Controls.Data;
using Sitecore.Form.Submit;
using System.Web;
using Sitecore.Web.UI.HtmlControls;
using Sitecore.Text;
using Sitecore.Forms.Core.Data;
using Sitecore.Form.Core.Configuration;
using Sitecore.Forms.Core.Crm;
using System;
using System.IO;
using System.Net;
using Sitecore.Diagnostics;
using System.Text;
namespace XXXWffmExternals
{
public class Redirect : ISaveAction
{
UrlString url = new UrlString("https://XXX.XXX/default.asp");
public virtual void Execute(ID formid, AdaptedResultList fields, params object[] data)
{
String strResult = "";
strResult = setPost(url.ToString(), fields);
}
public String setPost(string url, AdaptedResultList fieldListForPOST)
{
String resultReturn = "";
AdaptedControlResult firstname = fieldListForPOST.GetEntry(this.First_Name, "First_Name");
AdaptedControlResult lastname = fieldListForPOST.GetEntry(this.Last_Name, "Last_Name");
AdaptedControlResult billingaddress = fieldListForPOST.GetEntry(this.Billing_Address, "Billing_Address");
AdaptedControlResult billingcity = fieldListForPOST.GetEntry(this.Billing_City, "Billing_City");
AdaptedControlResult billingstate = fieldListForPOST.GetEntry(this.Billing_State, "Billing_State");
AdaptedControlResult billingzip = fieldListForPOST.GetEntry(this.Billing_Zip, "Billing_Zip");
AdaptedControlResult billingphone = fieldListForPOST.GetEntry(this.Billing_Phone, "Billing_Phone");
AdaptedControlResult email = fieldListForPOST.GetEntry(this.Email, "Email");
AdaptedControlResult amount = fieldListForPOST.GetEntry(this.Amount, "Amount");
AdaptedControlResult desc = fieldListForPOST.GetEntry(this.Description, "Description");
AdaptedControlResult login = fieldListForPOST.GetEntry(this.Login, "Login");
AdaptedControlResult acct = fieldListForPOST.GetEntry(this.Account, "Account");
AdaptedControlResult fund = fieldListForPOST.GetEntry(this.Fund, "Fund");
AdaptedControlResult org = fieldListForPOST.GetEntry(this.Org, "Org");
AdaptedControlResult source_code = fieldListForPOST.GetEntry(this.Source_Code, "Source_Code");
String post =
"First_Name=" + firstname.Value +
"&Last_Name=" + lastname.Value +
"&Billing_Address=" + billingaddress.Value +
"&Billing_City=" + billingcity.Value +
"&Billing_State=" + billingstate.Value +
"&Billing_Zip=" + billingzip.Value +
"&Billing_Phone=" + billingphone.Value +
"&Email=" + email.Value +
"&Amount=" + amount.Value +
"&Description=" + desc.Value +
"&Login=" + login.Value +
"&Account=" + acct.Value +
"&Fund=" + fund.Value +
"&Org=" + org.Value +
"&Invoice_Num=" + "DVXXXX";
resultReturn = sendPost(url.ToString(), post);
return resultReturn;
}
public String sendPost(string url, string post)
{
String result = "";
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
// Set credentials to use for this request.
objRequest.Credentials = CredentialCache.DefaultCredentials;
// Convert POST data to a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(post);
// Set the ContentLength property of the WebRequest.
objRequest.ContentLength = byteArray.Length;
// Set the ContentType property of the WebRequest.
objRequest.ContentType = "application/x-www-form-urlencoded";
// Get the request stream.
Stream dataStream = objRequest.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = objRequest.GetResponse();
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream ();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader (dataStream);
// Read the content.
result = reader.ReadToEnd ();
// Clean up the streams.
reader.Close ();
dataStream.Close ();
response.Close ();
return result;
}
public string First_Name { get; set; }
public string Last_Name { get; set; }
public string Billing_Address { get; set; }
public string Billing_City { get; set; }
public string Billing_State { get; set; }
public string Billing_Zip { get; set; }
public string Billing_Phone { get; set; }
public string Email { get; set; }
public string Amount { get; set; }
public string Description { get; set; }
public string Login { get; set; }
public string Account { get; set; }
public string Fund { get; set; }
public string Org { get; set; }
public string Invoice_Num { get; set; }
public string Source_Code { get; set; }
}
}
Why do you want to use WFFM for the form if you don't want to invoke any of the WFFM functionality? The point of WFFM is to allow marking people to create their own forms without any Developer input. You're having to edit all the post data in your code which pretty much eliminates the ability for anyone to edit the form without developer input. I'd say, if you're going to go through the process of writing all the code to submit your code by hand, you can use a Sitecore item to create the form and then use your own code for processing. Skip WFFM. It's a lot more work to do things as you suggested than to just manually create a form.
If you really need any WFFM end functionality, you can easily call them... it's still way easier than trying to override WFFM base functionality to inject your own functionality.
I am trying to use the SimpleRepository feature in Subsonic3 - first of all, I must say a big thanks to RobC - Subsonic really rocks, and I can't wait to see additional updates to the SimpleRepository. I am a big fan of the migration approach (developer/class driven rather than starting with the DB).
I have had a look at the post here:
Parent and Child object in SimpleRepository
but I am still a bit confused.
If I have got these classes defined:
public class Permit {
public int PermitID {get; set;}
public string Number { get; set; }
public DateTime? DateIssued { get; set; }
public Product product { get; set; }
}
public class Product
{
public int ProductID { get; set; }
public string Value { get; set; }
}
and then I want to save the data for a Permit, what should I be doing? Should I have defined a ProductID in the Permit class, and then programatically link them up? Or should the below code work?
var repo = new SimpleRepository("ECPermit", SimpleRepositoryOptions.RunMigrations);
var permit = new Permit();
var product = new Product();
permit.Number = "apermit";
permit.DateAdded = DateTime.Now;
product.Value = "this is a product";
repo.Add(permit);
permit.product = product;
repo.Add(product);
This is creating the Permit and Product table, but no links between them. What am I doing wrong?
Thanks
What you need to be aware of here is that the relationships are created by populating foreign keyvalues. So what you're doing in your example is creating a permit and saving it then setting the ProductID of the permit (but not saving this information), then saving the product. If you reorder your code as follows the ProductID will be set correctly:
var repo = new SimpleRepository("ECPermit", SimpleRepositoryOptions.RunMigrations);
var permit = new Permit();
var product = new Product();
product.Value = "this is a product";
repo.Add(product);
permit.Number = "apermit";
permit.DateAdded = DateTime.Now;
permit.ProductId = product.Id;
repo.Add(permit);