Using Unit test with IllRepack Plugin D365 - c#

I Would like to know how can i test my plugin in local?
To help me I using this link Write Unit Test for your Dataverse Plugins
In my case have some dependeces that main project plugin
The unit test:
namespace CRM.CLIENTE.Plugin.Test
{
[TestClass]
public class UnitTest1
{
[TestMethod]
[Description("Teste Template ")]
[Owner("Alexandre")]
public void TestMethod1()
{
Guid id = Guid.NewGuid();
// init
XrmFakedContext fakecontext = new XrmFakedContext();
XrmFakedPluginExecutionContext pluginContext = fakecontext.GetDefaultPluginContext();
XrmFakedTracingService iTracing = new XrmFakedTracingService();
//Prepare
Entity target = new Entity("Contact") { Id = id };
target.Attributes.Add("telephone1","90381290381 8876");
Entity postimage = new Entity("Contact") { Id = id };
postimage.Attributes.Add("telephone1", "90381290381 88763232");
ParameterCollection inputParameter = new ParameterCollection();
inputParameter.Add("Target", target);
EntityImageCollection postImages = new EntityImageCollection();
postImages.Add("PostImage", postimage);
pluginContext.InputParameters = inputParameter;
pluginContext.PostEntityImages = postImages;
fakecontext.Initialize(new List<Entity>() { postimage });
//Execute
fakecontext.ExecutePluginWith<PreOperationFormatPhoneCreateUpdate>(pluginContext);
//Assert
Entity teste = fakecontext.CreateQuery("Contact").FirstOrDefault();
Assert.Equals("903812903818876", teste["telephone1"]);
iTracing.Trace("Tested Trace in Account Create");
}
}
}
The main class of plugin
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using System.Text.RegularExpressions;
using CRM.CLIENTE.Plugin.Comum;
using CRM.CLIENTE.Plugin.Repository.Repository;
using CRM.CLIENTE.Plugin.Repository.Repository.Interface;
namespace CRM.CLIENTE.Plugin.Service
{
public class PreOperationFormatPhoneCreateUpdate : BasePlugin
{
protected override void ExecuteCrmPlugin(IPluginExecutionContext context, IOrganizationService service)
{
IContactRepository _contactRepository = new ContactRepository();
_contactRepository.formatarTelefone(context);
}
}
}
the base of plugin
namespace CRM.CLIENTE.Plugin.Comum
{
public abstract class BasePlugin : IPlugin
{
public IPluginExecutionContext localContext { get; set; }
public IOrganizationService OrganizationService { get; private set; }
public void Execute(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
{
throw new InvalidPluginExecutionException("serviceProvider");
}
try
{
localContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (!localContext.InputParameters.ContainsKey("Target"))
throw new InvalidPluginExecutionException("No target found");
IOrganizationService service = ((IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory))).CreateOrganizationService(null);
ExecuteCrmPlugin(localContext, service);
}
catch (InvalidPluginExecutionException e)
{
throw (e);
}
}
protected virtual void ExecuteCrmPlugin(IPluginExecutionContext localcontext, IOrganizationService service)
{
// Implementar o código do Plugin no proprio Plugin
}
}
}
The Repository Project
using CRM.CLIENTE.Plugin.Domain.Domain;
using CRM.CLIENTE.Plugin.Factory.Factory;
using CRM.CLIENTE.Plugin.Repository.Comum;
using CRM.CLIENTE.Plugin.Repository.Repository.Interface;
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace CRM.CLIENTE.Plugin.Repository.Repository
{
public class ContactRepository : IContactRepository
{
public Entity formatarTelefone(IPluginExecutionContext context)
{
Entity entity2 = context.InputParameters["Target"] as Entity;
Contact contato = new ContactFactory().d365ToObject(entity2);
contato.TelefoneComercial = Regex.Replace(contato.TelefoneComercial, #"[^\d]", "");
return new ContactFactory().objectToD365(contato);
}
}
}
The struture of my solution
Image Struture 1
Image Struture 1.1
Dependences main plugin
Image of error
Translate error
System.IO.FileLoadException: 'Could not load file or assembly 'CRM.CLIENTE.Plugin.Repository, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strong-named assembly is required. (Exception from HRESULT: 0x80131044)'
SO someone help me about this problem ?
I want use unit test to validate my plugin in local

Your plugin library is signed, because this is what is required by Dataverse.
As a consequence the projects your plugin project references must also be signed and this is also true for your test project.
Best practice is sharing one snk file and reference it from your projects. A quick fix is adding this snippet to the csproj files:
<PropertyGroup>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\CompanyKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

Related

Servicestack Test: Method not found: 'Int32 ServiceStack.DataAnnotations.CustomFieldAttribute.get_Order()

Trying to build integration test with connection to db in ServiceStack.
My ServiceStack app is working fine, but when I run simple test I got this error message in line:22
System.MissingMethodException: 'Method not found: 'Int32 ServiceStack.DataAnnotations.CustomFieldAttribute.get_Order()'.'
There is a lite cod:
using ServiceStack;
using ServiceStack.OrmLite;
using ServiceStack.Data;
using NUnit.Framework;
using ServiceStack.DataAnnotations;
using System.Collections.Generic;
namespace oth.Tests.IntegrationTests
{
public class AppHost2 : AppSelfHostBase
{
public AppHost2() : base("Customer REST Example", typeof(CustomerService).Assembly) { }
public override void Configure(Container container)
{
var connectionString = "Host=localhost;Port=5432;Database=test_1234;Username=postgres;Password=local";
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(connectionString, PostgreSqlDialect.Provider));
using var db = container.Resolve<IDbConnectionFactory>().Open();
db.CreateTableIfNotExists<Customer>();
}
}
public class Customer
{
[AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
}
[Route("/customers", "GET")]
public class GetCustomers : IReturn<GetCustomersResponse> { }
public class GetCustomersResponse
{
public List<Customer> Results { get; set; }
}
public class CustomerService : Service
{
public object Get(GetCustomers request)
{
return new GetCustomersResponse { Results = Db.Select<Customer>() };
}
}
public class CustomerRestExample
{
const string BaseUri = "http://localhost:2000/";
ServiceStackHost appHost;
public CustomerRestExample()
{
//Start your AppHost on TestFixture SetUp
appHost = new AppHost2()
.Init()
.Start(BaseUri);
}
[OneTimeTearDown]
public void OneTimeTearDown() => appHost.Dispose();
/* Write your Integration Tests against the self-host instance */
[Test]
public void Run_Customer_REST_Example()
{
var client = new JsonServiceClient(BaseUri);
var all = client.Get(new GetCustomers());
Assert.That(all.Results.Count, Is.EqualTo(0));
}
}
}
Anytime you see a missing type or missing method exceptions when using the MyGet pre-release packages it means you have a dirty installation (i.e. using pre-release packages from different build times).
In which case you'd need to Clear your Nuget packages cache and download the latest packages again, which ensures all your packages are from the latest same build:
$ dotnet nuget locals all -clear

Unable to resolve service for type while attempting to activate a service in startup.cs

Have spent way too much time trying to figure this out. Thanks for any help. .Net Core 3.1 trying to register a service in Startup.cs
Error CS0311: The type 'Apex.UI.MVC.ProjectService' cannot be used as type parameter 'TImplementation' in the generic type or method ServiceCollectionServiceExtensions.AddScoped<TService, TImplementation>(IServiceCollection). There is no implicit reference conversion from 'Apex.UI.MVC.ProjectService' to 'Apex.EF.Data.IProjects'. (CS0311) (Apex.UI.MVC)
services.AddScoped<IProjects, ProjectService>();
using System;
using Apex.EF.Data;
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;
using System.Linq;
using Apex.UI.MVC.Models.Projects;
namespace Apex.UI.MVC.Controllers
{
public class ProjectController : Controller
{
private IProjects _projects;
public ProjectController(IProjects projects)
{
_projects = projects;
}
public IActionResult Index()
{
var projectModels = _projects.GetAll();
var listingResult = projectModels
.Select(result => new ProjectIndexListingModel
{
Id = result.Id,
ProjectName = result.ProjectName,
ProjectImage = result.ProjectImage
});
var model = new ProjectIndexModel()
{
Project = listingResult
};
return View(model);
}
}
}
using System;
using System.Collections.Generic;
using Apex.EF.Data;
using Apex.EF.Data.Models;
namespace Apex.EF.Data
{
public interface IProjects
{
IEnumerable<Project> GetAll();
Project GetById(int id);
void Add(Project newProject);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Apex.EF.Data;
using Apex.EF.Data.Models;
using Microsoft.EntityFrameworkCore;
namespace ApexServices
{
public class ProjectService : IProjects
{
private ApexContext _context;
public ProjectService(ApexContext context)
{
_context = context;
}
public void Add(Project newProject)
{
_context.Add(newProject);
_context.SaveChanges();
}
public IEnumerable<Project> GetAll()
{
return _context.Projects
.Include(project => project.Status.IsInShop == true);
}
public Project GetById(int id)
{
return _context.Projects
.Include(project => project.Status.IsInShop==true)
.FirstOrDefault(project => project.Id == id);
}
}
}
The namespaces shown in the exception are different to the example code shown. There are probably conflicting types in the project (not shown).
If that is really the case, then include the full namespace when registering the type with the container to avoid conflicts.
Based on the shown code, that would be
services.AddScoped<IProjects, ApexServices.ProjectService>();

unable to save the inserted data after mapping

I'm trying to create a very simple C# program for insert the data.
Here is the service file :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using DataAccess;
using DataAccess.UoW;
using Model;
namespace ClassLibrary1
{
public class Service
{
private readonly Unit _uow;
public Service()
{
_uow = new Unit();
}
public bool CreateEmp(Mdl insertEntity)
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Mdl, Table_1>();
});
IMapper mapper = config.CreateMapper();
var Empinsert = mapper.Map<Mdl, Table_1>(insertEntity);
_uow.Register.Insert(Empinsert);
_uow.Save(); //this line shows error
return false;
}
}
}
Unit of Work:
using DataAccess.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataAccess.UoW
{
public class Unit
{
private guruEntities _context = null;
private Repository<Table_1> _register;
public Unit()
{
_context = new guruEntities();
}
public Repository<Table_1> Register
{
get
{
if (this._register == null)
this._register = new Repository<Table_1>(_context);
return _register;
}
}
}
}
And this is the error I get :
C# 'Unit' does not contain a definition for 'Save' and no accessible extension method 'Save' accepting a first argument of type 'Unit' could be found (are you missing a using directive or an assembly reference?)
You have to add save method in your Unit Class like this
public void Save()
{
context.SaveChanges();
}
for better understand you can refer Unitofwork class from below link
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

Azure mobile service - accessing a table controller from another custom controller

I am trying to access a table using its controller from another controller method.
But when the method tries to call the table controller method I get an exception:
Exception=System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.WindowsAzure.Mobile.Service.TableController.....
I manage to access the table controller method from the web API and execute it successfully.
I tried the same thing with TodoItem given as an example by the initial mobile service.
After several publishes to the server trying to fix the issue the web API stopped working and I get this exception : An exception of type 'Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException' occurred in mscorlib.dll but was not handled in user code
Additional information: The request could not be completed. (Internal Server Error) I managed to solve it when I reopened a mobile service and database with the exact same code that didn't work.
Any tips ?
Here is my table controller created by the controller wizard:
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.OData;
using Microsoft.WindowsAzure.Mobile.Service;
using FringProjectMobileService.DataObjects;
using FringProjectMobileService.Models;
namespace FringProjectMobileService.Controllers
{
public class StorageItemController : TableController<StorageItem>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
FringProjectMobileServiceContext context = new FringProjectMobileServiceContext();
DomainManager = new EntityDomainManager<StorageItem>(context, Request, Services);
}
// GET tables/StorageItem
public IQueryable<StorageItem> GetAllStorageItem()
{
return Query();
}
// GET tables/StorageItem/xxxxxxxxxx
public SingleResult<StorageItem> GetStorageItem(string id)
{
return Lookup(id);
}
// PATCH tables/StorageItem/xxxxxxxx
public Task<StorageItem> PatchStorageItem(string id, Delta<StorageItem> patch)
{
return UpdateAsync(id, patch);
}
// POST tables/StorageItem
public async Task<IHttpActionResult> PostStorageItem(StorageItem item)
{
StorageItem current = await InsertAsync(item);
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
// DELETE tables/StorageItem/xxxxxxxxxx
public Task DeleteStorageItem(string id)
{
return DeleteAsync(id);
}
}
}
Below the other controller code trying to access the method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Microsoft.WindowsAzure.Mobile.Service;
namespace FringProjectMobileService.Controllers
{
public class ArduinoController : ApiController
{
public ApiServices Services { get; set; }
// GET api/Arduino
public string Get()
{
Services.Log.Info("Hello from custom controller!");
return "Hello";
}
public async void PostProcessTag(String id)
{
Microsoft.WindowsAzure.MobileServices.MobileServiceClient client = new Microsoft.WindowsAzure.MobileServices.MobileServiceClient("http://some-service.azure-mobile.net", "XXXXXXXXXXXXXXX");
Microsoft.WindowsAzure.MobileServices.IMobileServiceTable<DataObjects.StorageItem> storage_item_table = client.GetTable<DataObjects.StorageItem>();
await storage_item_table.ToEnumerableAsync();
}
}
}
I also tried a different implementation for the method :
public void PostProcessTag(String id)
{
StorageItemController table_controller = new StorageItemController();
IQueryable<DataObjects.StorageItem> item = table_controller.GetAllStorageItem();
}
The service context:
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using Microsoft.WindowsAzure.Mobile.Service;
using Microsoft.WindowsAzure.Mobile.Service.Tables;
namespace FringProjectMobileService.Models
{
public class FringProjectMobileServiceContext : DbContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to alter your database
// automatically whenever you change your model schema, please use data migrations.
// For more information refer to the documentation:
// http://msdn.microsoft.com/en-us/data/jj591621.aspx
//
// To enable Entity Framework migrations in the cloud, please ensure that the
// service name, set by the 'MS_MobileServiceName' AppSettings in the local
// Web.config, is the same as the service name when hosted in Azure.
private const string connectionStringName = "Name=MS_TableConnectionString";
public FringProjectMobileServiceContext() : base(connectionStringName)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
string schema = ServiceSettingsDictionary.GetSchemaName();
if (!string.IsNullOrEmpty(schema))
{
modelBuilder.HasDefaultSchema(schema);
}
modelBuilder.Conventions.Add(
new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
"ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));
}
public System.Data.Entity.DbSet<FringProjectMobileService.DataObjects.StorageItem> StorageItems { get; set; }
}
}

Google Drive "get_error not implemented" error

I'm trying to implement the use of Google Drive in my app but I seem to be getting the following error "Method 'get_Error' in type 'Google.Apis.Drive.v2.Data.FileList' from assembly 'Google.Apis.Drive.v2, Version=1.2.4647.29713, Culture=neutral, PublicKeyToken=null' does not have an implementation". Does anyone know as to why this is occurring? I based my code on the example that Google provides for its tasks API.
Code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Util;
using System.Diagnostics;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Util;
using PrepHub.PrepHub;
using System.Web.Services;
using System.Threading;
using Google.Apis;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Drive.v2;
using Google.Apis.Drive;
namespace DriveExample
{
public partial class GDrive : System.Web.UI.Page
{
private static DriveService _service; // We don't need individual service instances for each client.
private OAuth2Authenticator<WebServerClient> _authenticator;
private IAuthorizationState _state;
private IAuthorizationState AuthState
{
get
{
return _state ?? HttpContext.Current.Session["AUTH_STATE"] as IAuthorizationState;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (_service == null)
{
_service = new DriveService(_authenticator = CreateAuthenticator());
}
if (HttpContext.Current.Request["code"] != null)
{
_authenticator = CreateAuthenticator();
_authenticator.LoadAccessToken();
}
var ni = _service.Files.List().Fetch();
}
private OAuth2Authenticator<WebServerClient> CreateAuthenticator()
{
var provider = new WebServerClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = ClientCredentials.ClientID;
provider.ClientSecret = ClientCredentials.ClientSecret;
var authenticator =
new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization) { NoCaching = true };
return authenticator;
}
private IAuthorizationState GetAuthorization(WebServerClient client)
{
// If this user is already authenticated, then just return the auth state.
IAuthorizationState state = AuthState;
if (state != null)
{
return state;
}
// Check if an authorization request already is in progress.
state = client.ProcessUserAuthorization(new HttpRequestInfo(HttpContext.Current.Request));
if (state != null && (!string.IsNullOrEmpty(state.AccessToken) || !string.IsNullOrEmpty(state.RefreshToken)))
{
// Store and return the credentials.
HttpContext.Current.Session["AUTH_STATE"] = _state = state;
return state;
}
string scope = DriveService.Scopes.Drive.GetStringValue();
OutgoingWebResponse response = client.PrepareRequestUserAuthorization(new[] { scope });
response.Send();
return null;
}
}
}
I'm guessing some of your assemblies are out of date. That error will occur when you have an assembly for example, lets say foo.dll (v1) and that assembly is being referenced by bar.dll (v2). A class in bar.dll is expecting something in to be present on a class in Foo and its not there. In your case, its the get accessor for a property called Error on the class FileList. Double check all your assemblies to make sure they are all at their most recent version (s).

Categories