Σημείωμα
Η πρόσβαση σε αυτήν τη σελίδα απαιτεί εξουσιοδότηση. Μπορείτε να δοκιμάσετε να εισέλθετε ή να αλλάξετε καταλόγους.
Η πρόσβαση σε αυτήν τη σελίδα απαιτεί εξουσιοδότηση. Μπορείτε να δοκιμάσετε να αλλάξετε καταλόγους.
Μπορείτε να χρησιμοποιήσετε μια προσαρμοσμένη προσθήκη για να λάβετε γεωχωρικά δεδομένα από την υπηρεσία παροχής δεδομένων που προτιμάτε αντί να χρησιμοποιήσετε το προεπιλεγμένο API στο Dynamics 365 Field Service και το Project Operations. Αυτό το άρθρο καλύπτει τις γεωχωρικές ενέργειες URS, τις απαιτούμενες παραμέτρους εισόδου και εξόδου και τα μοτίβα υλοποίησης για αιτήματα γεωκωδικοποίησης και μήτρας απόστασης. Τα παραδείγματα χρησιμοποιούν το Google Maps API για να απεικονίσουν την προσέγγιση, αλλά το ίδιο μοτίβο ισχύει και για άλλους παρόχους.
Παράμετροι εισόδου και εξόδου για γεω-χωρικές ενέργειες
Κατά τη σύνταξη της προσαρμοσμένης προσθήκης, εξετάστε τις παραμέτρους εισόδου και εξόδου για τις γεωχωρικές ενέργειες για να κατανοήσετε ποια δεδομένα πρέπει να μεταβιβάσετε και τα αναμενόμενα δεδομένα εξόδου στον πρόσθετο κώδικά σας.
Μπορείτε να δείτε τις παραμέτρους εισόδου και εξόδου για τις δύο γεωχωρικές ενέργειες με δύο τρόπους:
-
Περιεχόμενο αναφοράς ενέργειας web API: Προβολή πληροφοριών αναφοράς σχετικά με γεω-χωρικές ενέργειες στο Universal Resource Scheduling.
Microsoft.Dynamics.CRM.msdyn_RetrieveDistanceMatrix
- Ορισμός ενέργειας: Προβάλετε τον ορισμό ενέργειας στο Dynamics 365 για πληροφορίες σχετικά με τις παραμέτρους εισόδου/εξόδου, συμπεριλαμβανομένων πληροφοριών εάν μια παράμετρος είναι απαραίτητη ή προαιρετική.
Σημείωμα
Οι τύποι και οι λειτουργίες του Web API που αναφέρονται σε αυτό το άρθρο είναι διαθέσιμοι στο περιβάλλον σας. Μπορείτε να τα εξερευνήσετε χρησιμοποιώντας το έγγραφο υπηρεσίας του περιβάλλοντός σας ή την Αϋπνία. Μάθετε περισσότερα στα Έγγραφα υπηρεσίας Web API και χρησιμοποιήστε την αϋπνία με το Microsoft Dataverse Web API.
Προβολή ορισμού ενέργειας
Συνδεθείτε στο Power Apps και επιλέξτε το περιβάλλον σας.
Ανοίξτε τη λύση σας και επιλέξτε Αντικείμενα.
Ανοίξτε τις Διαδικασίες και κάντε αναζήτηση για το όνομα της ενέργειας, όπως Προγραμματισμός πόρων - Διεύθυνση γεωγραφικού κώδικα ή Προγραμματισμός πόρων - Ανάκτηση μήτρας απόστασης.
Ανοίξτε το όνομα της ενέργειας. Για παράδειγμα, το στιγμιότυπο οθόνης δείχνει τον ορισμό της ενέργειας Προγραμματισμός πόρων - Διεύθυνση γεωγραφικού κωδικού (msdyn_GeocodeAddress) όπου η περιοχή με επισήμανση παρέχει πληροφορίες σχετικά με τις παραμέτρους εισόδου και εξόδου:
Συντάξτε την προσαρμοσμένη σας προσθήκη
Οι προσθήκες είναι προσαρμοσμένες κλάσεις που υλοποιούν το IPlugin περιβάλλον εργασίας. Για να δημιουργήσετε μια προσθήκη, μεταβείτε στην ανάπτυξη προσθηκών
Για την αναφορά σας παρέχεται ένα προσαρμοσμένο δείγμα προσθήκης που δείχνει πώς μπορείτε να χρησιμοποιήσετε το API του Google Maps για την παροχή γεωχωρικών δεδομένων για λειτουργίες πεδίου αντί για το προεπιλεγμένο API. Μάθετε περισσότερα στο Δείγμα: Προσαρμοσμένη προσθήκη για χρήση του API Google Maps ως υπηρεσίας παροχής γεωχωρικών δεδομένων.
Ο παρακάτω κώδικας σε κάθε δείγμα προσθήκης χρησιμοποιεί δεδομένα από το Google API:
Η μέθοδος ExecuteGeocodeAddress στο αρχείο msdyn_GeocodeAddress.cs προσθηκών
public void ExecuteGeocodeAddress(IPluginExecutionContext pluginExecutionContext, IOrganizationService organizationService, ITracingService tracingService)
{
//Contains 5 fields (string) for individual parts of an address
ParameterCollection InputParameters = pluginExecutionContext.InputParameters;
// Contains 2 fields (double) for resultant geolocation
ParameterCollection OutputParameters = pluginExecutionContext.OutputParameters;
//Contains 1 field (int) for status of previous and this plugin
ParameterCollection SharedVariables = pluginExecutionContext.SharedVariables;
tracingService.Trace("ExecuteGeocodeAddress started. InputParameters = {0}, OutputParameters = {1}", InputParameters.Count().ToString(), OutputParameters.Count().ToString());
try
{
// If a plugin earlier in the pipeline has already geocoded successfully, quit
if ((double)OutputParameters[LatitudeKey] != 0d || (double)OutputParameters[LongitudeKey] != 0d) return;
// Get user Lcid if request did not include it
int Lcid = (int)InputParameters[LcidKey];
string _address = string.Empty;
if (Lcid == 0)
{
var userSettingsQuery = new QueryExpression("usersettings");
userSettingsQuery.ColumnSet.AddColumns("uilanguageid", "systemuserid");
userSettingsQuery.Criteria.AddCondition("systemuserid", ConditionOperator.Equal, pluginExecutionContext.InitiatingUserId);
var userSettings = organizationService.RetrieveMultiple(userSettingsQuery);
if (userSettings.Entities.Count > 0)
Lcid = (int)userSettings.Entities[0]["uilanguageid"];
}
// Arrange the address components in a single comma-separated string, according to LCID
_address = GisUtility.FormatInternationalAddress(Lcid,
(string)InputParameters[Address1Key],
(string)InputParameters[PostalCodeKey],
(string)InputParameters[CityKey],
(string)InputParameters[StateKey],
(string)InputParameters[CountryKey]);
// Make Geocoding call to Google API
WebClient client = new WebClient();
var url = $"https://{GoogleConstants.GoogleApiServer}{GoogleConstants.GoogleGeocodePath}/json?address={_address}&key={GoogleConstants.GoogleApiKey}";
tracingService.Trace($"Calling {url}\n");
string response = client.DownloadString(url); // Post ...
tracingService.Trace("Parsing response ...\n");
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(GeocodeResponse)); // Deserialize response json
object objResponse = jsonSerializer.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(response))); // Get response as an object
GeocodeResponse geocodeResponse = objResponse as GeocodeResponse; // Unbox into our data contracted class for response
tracingService.Trace("Response Status = " + geocodeResponse.Status + "\n");
if (geocodeResponse.Status != "OK")
throw new ApplicationException($"Server {GoogleConstants.GoogleApiServer} application error (Status {geocodeResponse.Status}).");
tracingService.Trace("Checking geocodeResponse.Result...\n");
if (geocodeResponse.Results != null)
{
if (geocodeResponse.Results.Count() == 1)
{
tracingService.Trace("Checking geocodeResponse.Result.Geometry.Location...\n");
if (geocodeResponse.Results.First()?.Geometry?.Location != null)
{
tracingService.Trace("Setting Latitude, Longitude in OutputParameters...\n");
// update output parameters
OutputParameters[LatitudeKey] = geocodeResponse.Results.First().Geometry.Location.Lat;
OutputParameters[LongitudeKey] = geocodeResponse.Results.First().Geometry.Location.Lng;
}
else throw new ApplicationException($"Server {GoogleConstants.GoogleApiServer} application error (missing Results[0].Geometry.Location)");
}
else throw new ApplicationException($"Server {GoogleConstants.GoogleApiServer} application error (more than 1 result returned)");
}
else throw new ApplicationException($"Server {GoogleConstants.GoogleApiServer} application error (missing Results)");
}
catch (Exception ex)
{
// Signal to subsequent plugins in this message pipeline that geocoding failed here.
OutputParameters[LatitudeKey] = 0d;
OutputParameters[LongitudeKey] = 0d;
//TODO: You may need to decide which caught exceptions will rethrow and which ones will simply signal geocoding did not complete.
throw new InvalidPluginExecutionException(string.Format("Geocoding failed at {0} with exception -- {1}: {2}"
, GoogleConstants.GoogleApiServer, ex.GetType().ToString(), ex.Message), ex);
}
}
Μέθοδος ExecuteDistanceMatrix στο αρχείο προσθήκης msdyn_RetrieveDistanceMatrix.cs
public void ExecuteDistanceMatrix(IPluginExecutionContext pluginExecutionContext, IOrganizationService organizationService, ITracingService tracingService)
{
//Contains 2 fields (EntityCollection) for sources and targets
ParameterCollection InputParameters = pluginExecutionContext.InputParameters;
// Contains 1 field (EntityCollection) for results
ParameterCollection OutputParameters = pluginExecutionContext.OutputParameters;
//Contains 1 field (int) for status of previous and this plugin
ParameterCollection SharedVariables = pluginExecutionContext.SharedVariables;
tracingService.Trace("ExecuteDistanceMatrix started. InputParameters = {0},OutputParameters = {1}", InputParameters.Count().ToString(), OutputParameters.Count().ToString());
try
{
// If a plugin earlier in the pipeline has already retrieved a distance matrix successfully, quit
if (OutputParameters[MatrixKey] != null)
if (((EntityCollection)OutputParameters[MatrixKey]).Entities != null)
if (((EntityCollection)OutputParameters[MatrixKey]).Entities.Count > 0) return;
// Make Distance Matrix call to Google API
WebClient client = new WebClient();
var url = String.Format($"https://{GoogleConstants.GoogleApiServer}{GoogleConstants.GoogleDistanceMatrixPath}/json"
+ "?units=imperial"
+ $"&origins={string.Join("|", ((EntityCollection)InputParameters[SourcesKey]).Entities.Select(e => e.GetAttributeValue<double?>("latitude") + "," + e.GetAttributeValue<double?>("longitude")))}"
+ $"&destinations={string.Join("|", ((EntityCollection)InputParameters[TargetsKey]).Entities.Select(e => e.GetAttributeValue<double?>("latitude") + "," + e.GetAttributeValue<double?>("longitude")))}"
+ $"&key={GoogleConstants.GoogleApiKey}");
tracingService.Trace($"Calling {url}\n");
string response = client.DownloadString(url); // Post ...
tracingService.Trace("Parsing response ...\n");
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(DistanceMatrixResponse)); // Deserialize response json
object objResponse = jsonSerializer.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(response))); // Get response as an object
DistanceMatrixResponse distancematrixResponse = objResponse as DistanceMatrixResponse; // Unbox as our data contracted class for response
tracingService.Trace("Response Status = " + distancematrixResponse.Status + "\n");
if (distancematrixResponse.Status != "OK")
throw new ApplicationException($"Server {GoogleConstants.GoogleApiServer} application error (Status={distancematrixResponse.Status}). {distancematrixResponse.ErrorMessage}");
tracingService.Trace("Checking distancematrixResponse.Results...\n");
if (distancematrixResponse.Rows != null)
{
tracingService.Trace("Parsing distancematrixResponse.Results.Elements...\n");
// build and update output parameter
var result = new EntityCollection();
result.Entities.AddRange(distancematrixResponse.Rows.Select(r => ToEntity(r.Columns.Select(c => ToEntity(c.Status, c.Duration, c.Distance)).ToArray())));
OutputParameters[MatrixKey] = result;
}
else throw new ApplicationException($"Server {GoogleConstants.GoogleApiServer} application error (missing Rows)");
}
catch (Exception ex)
{
// Signal to subsequent plugins in this message pipeline that retrieval of distance matrix failed here.
OutputParameters[MatrixKey] = null;
//TODO: You may need to decide which caught exceptions will rethrow and which ones will simply signal geocoding did not complete.
throw new InvalidPluginExecutionException(string.Format("Geocoding failed at {0} with exception -- {1}: {2}"
, GoogleConstants.GoogleApiServer, ex.GetType().ToString(), ex.Message), ex);
}
// For debugging purposes, throw an exception to see the details of the parameters
CreateExceptionWithDetails("Debugging...", InputParameters, OutputParameters, SharedVariables);
}
Μετά τη σύνταξη του προσαρμοσμένου κώδικα προσθήκης, δημιουργήστε το έργο για τη δημιουργία μιας συγκρότησης προσθήκης (.dll) . Χρησιμοποιήστε αυτήν τη συγκρότηση για να καταχωρήσετε την προσθήκη στις γεωχωρικές ενέργειες Universal Resource Scheduling.