public static async Task Main(string[] args) { using var builder = new HostBuilder() .ConfigureAppConfiguration((hostContext, config) => { string basePath = GetApplicationRoot(); if (string.IsNullOrWhiteSpace(basePath)) { basePath = Directory.GetCurrentDirectory(); } Directory.SetCurrentDirectory(basePath); config.SetBasePath(basePath); config.AddJsonFile("appsettings.json", true); if (args != null) { config.AddCommandLine(args); } }) .ConfigureServices((hostContext, services) => { // 1) Register HttpClientFactory services.AddHttpClient(); // 2) Register the IRetsRequester services.AddTransient <IRetsRequester, RetsWebRequester>(); // 3) Register the IRetsSession services.AddTransient <IRetsSession, RetsSession>(); // 4) Register the IRetsClient services.AddTransient <IRetsClient, RetsClient>(); // 5) Register the ILogger services.AddLogging(); // 6) Register the connection options services.AddOptions <ConnectionOptions>() .Configure((opts) => { opts.UserAgent = hostContext.Configuration["Rets:UserAgent"]; opts.RetsServerVersion = RetsVersion.Make(hostContext.Configuration["Rets:ServerVersion"]); opts.LoginUrl = hostContext.Configuration["Rets:LoginUrl"]; opts.Username = hostContext.Configuration["Rets:Username"]; opts.Password = hostContext.Configuration["Rets:Password"]; opts.UserAgentPassward = hostContext.Configuration["Rets:UserAgentPassward"]; opts.Type = Enum.Parse <AuthenticationType>(hostContext.Configuration["Rets:Type"], true); opts.Timeout = TimeSpan.FromHours(1); }); RegisterExamples(services); }) .ConfigureLogging((hostContext, logging) => { logging.ClearProviders(); logging.AddConsole(); logging.SetMinimumLevel(LogLevel.Information); }).Build(); // by default we'll invoke the main Example string exampleNameToInvoke = args.Length > 0 ? args[0] : nameof(Example); await InvokeExample(exampleNameToInvoke, builder.Services); await builder.StopAsync(); }
/* * This class demonstrates the interleaving of search transactions. */ static void Main(string[] args) { Options options = new Options(); if (!options.Parse(args)) { Environment.Exit(1); } RetsSession session = options.SessionFactory(); try { if (!session.Login(options.user_name, options.user_password)) { Console.WriteLine("Invalid login"); Environment.Exit(1); } } catch (Exception e) { Console.WriteLine("RetsException: " + e); Environment.Exit(1); } RetsVersion version = session.GetDetectedRetsVersion(); Console.WriteLine("RETS Version: " + ((version == RetsVersion.RETS_1_5) ? "1.5" : ((version == RetsVersion.RETS_1_7) ? "1.7" : "1.0"))); /* * Find the key field for the resource. */ RetsMetadata metadata = session.GetMetadata(); MetadataResource metadataResource = metadata.GetResource(options.search_type); if (metadataResource == null) { Console.WriteLine("Invalid resource: " + options.search_type); session.Logout(); Environment.Exit(1); } string keyField = metadataResource.GetKeyField(); /* * Find the timestamp field if it is known (RETS 1.7 and later). If * not known, then the user must provide it. */ MetadataClass metadataClass = metadata.GetClass(options.search_type, options.search_class); if (metadataClass == null) { Console.WriteLine("Invalid resource:class: " + options.search_type + ":" + options.search_class); session.Logout(); Environment.Exit(2); } if (options.classTimeStamp != null && options.classTimeStamp.Length == 0) { options.classTimeStamp = metadataClass.GetStringAttribute("ClassTimeStamp"); } if (options.classTimeStamp == null || options.classTimeStamp.Length == 0) { Console.WriteLine("Class " + options.search_type + ":" + options.search_class + " has no ClassTimeStamp specified in the metadata."); Console.WriteLine("Please manually provide one using the --timetsamp switch."); session.Logout(); Environment.Exit(2); } /* * See if the last modified timestamp has been provided. If not, use yesterday. */ if (options.lastModified == null || options.lastModified.Length == 0) { DateTime ts = DateTime.Now; options.lastModified = ts.AddDays(-1).ToString("yyyy-MM-dd"); } /* * OK - let's find all listings that have changed since the lastModified date. */ SearchRequest searchRequest = session.CreateSearchRequest( options.search_type, options.search_class, "(" + options.classTimeStamp.ToString() + "=" + options.lastModified.ToString() + "+)"); searchRequest.SetSelect(keyField); searchRequest.SetLimit(SearchRequest.LIMIT_NONE); searchRequest.SetOffset(SearchRequest.OFFSET_NONE); searchRequest.SetCountType(SearchRequest.CountType.RECORD_COUNT_AND_RESULTS); searchRequest.SetStandardNames(false); /* * This starts the outer search. */ SearchResultSet results = session.Search(searchRequest); Console.WriteLine("Record count: " + results.GetCount()); Console.WriteLine(); while (results.HasNext()) { /* * Fetch the listing detail and media. This will cause a separate search transaction * to be open within the outer search transaction. */ SearchRequest listingRequest = session.CreateSearchRequest( options.search_type, options.search_class, "(" + keyField + "=" + results.GetString(keyField) + ")"); listingRequest.SetStandardNames(false); listingRequest.SetLimit(SearchRequest.LIMIT_DEFAULT); listingRequest.SetOffset(SearchRequest.OFFSET_NONE); listingRequest.SetCountType(SearchRequest.CountType.NO_RECORD_COUNT); listingRequest.SetFormatType(SearchRequest.FormatType.COMPACT); SearchResultSet listingResult = session.Search(listingRequest); IEnumerable columns = null; while (listingResult.HasNext()) { if (columns == null) { columns = listingResult.GetColumns(); } /* * Show the listing detail. */ foreach (string column in columns) { Console.WriteLine("{0,15}: {1}", column, listingResult.GetString(column)); } Console.WriteLine(); /* * Now set up to fetch the objects associated with this listing. */ GetObjectRequest getObjectRequest = new GetObjectRequest(options.search_type, "Photo"); getObjectRequest.AddAllObjects(listingResult.GetString(keyField)); GetObjectResponse getObjectResponse = session.GetObject(getObjectRequest); foreach (ObjectDescriptor objectDescriptor in getObjectResponse) { /* * Report the object details. */ string objectKey = objectDescriptor.GetObjectKey(); int objectId = objectDescriptor.GetObjectId(); //string contentType = objectDescriptor.GetContentType(); string description = objectDescriptor.GetDescription(); Console.Write("Object " + objectKey + ":" + objectId.ToString()); if (description.Length > 0) { Console.Write(", description: " + description); } Console.WriteLine(); } Console.WriteLine("================="); } } session.Logout(); }
static void Main(string[] args) { Options options = new Options(); if (!options.Parse(args)) { Environment.Exit(1); } RetsSession session = options.SessionFactory(); try { if (!session.Login(options.user_name, options.user_password)) { Console.WriteLine("Invalid login"); Environment.Exit(1); } } catch (Exception e) { Console.WriteLine("RetsException: " + e); Environment.Exit(1); } Console.WriteLine("Action: " + session.GetAction()); RetsVersion version = session.GetDetectedRetsVersion(); Console.WriteLine("RETS Version: " + ((version == RetsVersion.RETS_1_5) ? "1.5" : ((version == RetsVersion.RETS_1_7) ? "1.7" : "1.0"))); SearchRequest searchRequest = session.CreateSearchRequest( options.search_type, options.search_class, options.query); searchRequest.SetSelect(options.select); searchRequest.SetLimit(options.limit); searchRequest.SetOffset(options.offset); searchRequest.SetCountType(options.count); searchRequest.SetStandardNames(options.standard_names); searchRequest.SetRestrictedIndicator("XXXX"); searchRequest.SetFormatType(SearchRequest.FormatType.COMPACT); SearchResultSet results = session.Search(searchRequest); Console.WriteLine("Record count: " + results.GetCount()); Console.WriteLine(); IEnumerable columns = null; while (results.HasNext()) { if (columns == null) { columns = results.GetColumns(); } foreach (string column in columns) { Console.WriteLine(column + ": " + results.GetString(column)); } Console.WriteLine(); } LogoutResponse logout = session.Logout(); Console.WriteLine("Billing info: " + logout.GetBillingInfo()); Console.WriteLine("Logout message: " + logout.GetLogoutMessage()); Console.WriteLine("Connect time: " + logout.GetConnectTime()); }
public static async Task Main(string[] args) { InitilizeApp(); // First we need to set out configuration Service.AddTransient(opts => new ConnectionOptions() { UserAgent = Configuration["Rets:UserAgent"], RetsServerVersion = RetsVersion.Make(Configuration["Rets:ServerVersion"]), LoginUrl = Configuration["Rets:LoginUrl"], Username = Configuration["Rets:Username"], Password = Configuration["Rets:Password"], UserAgentPassward = Configuration["Rets:UserAgentPassward"], Type = Enum.Parse <AuthenticationType>(Configuration["Rets:Type"], true), Timeout = TimeSpan.FromHours(1), }); // Register the IRetsRequester, IRetsSession, IRetsClient Service.AddTransient <IRetsRequester, RetsWebRequester>(); Service.AddTransient <IRetsSession, RetsSession>(); Service.AddTransient <IRetsClient, RetsClient>(); // Create out IoC container Container = Service.BuildServiceProvider(); // Get instance of the IRetsClient from the IoC IRetsClient client = Container.GetService <IRetsClient>(); // The first request we make to the RETS server is to login await client.Connect(); // To get to know the RETS server, we can scan the entire system to get a list of our resources, classes, object..... RetsSystem system = await client.GetSystemMetadata(); // We can also get a list of all available resources RetsResourceCollection resources = await client.GetResourcesMetadata(); // We can also get all available classes for a given resorce. Assuming your RETS server has a resource called "Property" RetsClassCollection classes = await client.GetClassesMetadata("Property"); // We can also get a list of all available objects on a given property. RetsObjectCollection objects = await client.GetObjectMetadata("Property"); // We can also get a list of all available field for the given resource and class. Assuming your RETS server has a resource called "Property" with a class called "Listing" RetsFieldCollection fields = await client.GetTableMetadata("Property", "Listing"); // We can also get all available lookup values on the given resource IEnumerable <RetsLookupTypeCollection> lookupTypes = await client.GetLookupValues("Property"); // We can also get a list of all available lookup types for a give resource and lookuptype aka fieldName RetsLookupTypeCollection lookupType = await client.GetLookupValues("Property", "FieldName"); // We can perform a search against the RETS server SearchRequest searchRequest = new SearchRequest("Property", "Listing"); // Add ad many parameers to search for. Assuming the class "Listing" on the "Property" resource has a field called "matrix_unique_id" which is numeric type // we say give me all properties where matrix_unique_id >= 0 searchRequest.ParameterGroup.AddParameter(new QueryParameter("matrix_unique_id", "0+")); // If you like to return specific columns, you can do so like this searchRequest.AddColumn("matrix_unique_id"); searchRequest.AddColumn("SomeOtherColumnName"); // This performs the search against the server SearchResult result = await client.Search(searchRequest); // we can iterate over the results like so foreach (SearchResultRow row in result.GetRows()) { // Each row has multiple columns, lets loop over them foreach (var columnName in result.GetColumns()) { // Lets get the cell value for a given column from the current row SearchResultCellValue value = row.Get(columnName); // you can get the value trimmed like so string a = value.GetTrimmed(); string b = value.NullOrValue(); // Assuming you know the type of the returned data, you can cast the values like so // Of cource you must know that the column is int type befor eyou call this //int castedToIntValue = value.Get<int>(); //you can also do something like //int? castedToIntValue = value.GetNullable<int>(); //DateTime? castedToIntValue = value.GetNullable<DateTime>(); // you can also check if the value is restricted like this bool restrictedValue = value.IsRestricted; // you can check if this value is a primary key bool primaryKey = value.IsPrimaryKeyValue; bool c = value.IsNullOrEmpty(); bool d = value.IsNullOrWhiteSpace(); bool e = value.IsNull(); } } // Also you can extract only all value for a given column like this IEnumerable <SearchResultCellValue> createdAtCells = result.Pluck("CreatedAt"); // you can also result cast the values of a given field like this // this will result an IEnumerable<> of all values found in the CreatedAt column IEnumerable <DateTime> createdAtvalues = result.Pluck <DateTime>("CreatedAt"); // We can also download photos // This will return all photos for property with the primarykey 1234 IEnumerable <FileObject> files = await client.GetObject("Property", "Photo", new PhotoId(1234), false); // Here is how we can iterate over the fields foreach (FileObject file in files) { var filePath = $"{file.ContentId}/{file.ObjectId}{file.Extension}"; using (FileStream output = File.Create("../../../Downloads/" + filePath)) { // file.Content has the stream object where you can write it your storage file.Content.CopyTo(output); // IMPORTANT: Make sure you dispose the stram after finising using it file.Dispose(); } } // you can get a specific image for a given primary key like so IEnumerable <FileObject> files2 = await client.GetObject("Property", "Photo", new PhotoId(1234, 1), false); // you can get also get images for multiple primary keys at the same time like this List <PhotoId> photoIds = new List <PhotoId>() { new PhotoId(1234), new PhotoId(5678), new PhotoId(2255) }; IEnumerable <FileObject> files3 = await client.GetObject("Property", "Photo", photoIds, false); // When you are trying to download lots of images you must be very carfult. If you send the server too many ids at the same time // the server may return 404, 414, 500 or something along these lines because the request is too long. // Also, the server may take long time to response which will case the HTTP request to timeout. // So solve for the timeout issue we can increate the HTTP timeout from ConnectionOptions() object. // However, there is a better more reliable solution to this prblem which is the ability to batch the request into multiple request // Assume we want to download images for 1000 properties. Assume that each property on average has 15 photos, this will result in downloading 1000 x 15 = 15,000 images // We can split the 1000 properties into a smaller number like 100. This will make 10 (i.e 1000/100) request to the RETS server then return you an object of 15,000 images // You may want to still be careful because there will be 15,000 stored in the memory, so make sure you're not going to run our of memory // Anyhow, batching can easily be done like this IEnumerable <FileObject> batchedFiles = await client.GetObject("Property", "Photo", photoIds, batchSize : 100); // Finally we can disconect await client.Disconnect(); // The above code require us to First connect, then Disconnect when we are done. Not too bad, but we can simplfy the call by using // a method called RoundTrip() which will first connect, execure out code, then disconnect // to save some code you can do call RoundTrip() which will connect, call out method, then discconnect(); IEnumerable <FileObject> files4 = await client.RoundTrip(async() => { // Each batch will cause a round trip. In other words, each batch will connect, download a batch, then disconnect. return(await client.GetObject("Property", "Photo", photoIds, batchSize: 20)); }); }