based on docs, there are some known exception types in bit-framework.
https://docs.bit-framework.com/docs/bit-server-side/web-api.html#exceptions
How can we extend this list?
Take a look at following code:
public class MyException : Exception, IKnownException /*Required*/, IHttpStatusCodeAwareException /*Optional >> Default is InternalServerError (500)*/
{
public MyException(string message)
: base(message)
{
}
public HttpStatusCode StatusCode { get; set; } = HttpStatusCode.Conflict;
}
Hope this helps
Related
Does anyone know how I can mark an argument on ActionDescriptor.Parameters to behave in a similar way the [BindNever] is behaving?
I want to always exclude a specific argument from a specific type without keep decorating it on the Controller.
Essentially I would like to be able to add my injected to my functions somehow how similar to the way its done with CancellationToken
public class TestController : ControllerBase
{
[HttpGet(Name = "Get")]
public IActionResult Get([BindNever] IInjectedInterface injected)
{
//Injected can be used in this method
return Ok();
}
[HttpPost(Name = "Post")]
public IActionResult Post([BindNever] IInjectedInterface injected, FormModel formModel)
{
//Injected doesn't work here. There is an error that
/*System.InvalidOperationException: 'Action 'WebApplication3.Controllers.TestController.Post (WebApplication3)'
has more than one parameter that was specified or inferred as bound from request body. Only one parameter per action may be bound from body.
Inspect the following parameters, and use 'FromQueryAttribute' to specify bound from query, 'FromRouteAttribute' to specify bound from route,
and 'FromBodyAttribute' for parameters to be bound from body:
IInjectedInterface injected
FormModel formModel'
*/
return Ok();
}
}
public class ActionExecutionFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var injectedParam = context.ActionDescriptor.Parameters.SingleOrDefault(x => x.ParameterType == typeof(IInjectedInterface));
if (injectedParam != null)
{
context.ActionArguments[injectedParam.Name] = new Injected(99);
}
await next.Invoke();
}
private class Injected : IInjectedInterface
{
public Injected(int someData)
{
SomeData = someData;
}
public int SomeData { get; }
}
}
I was able to solve it. Apparently you need to add the following lines on your program.cs to avoid the model binder related errors.
options.ModelMetadataDetailsProviders.Add(
new ExcludeBindingMetadataProvider(typeof(IInjectedInterface)));
options.ModelMetadataDetailsProviders.Add(
new BindingSourceMetadataProvider(typeof(IInjectedInterface), BindingSource.Special));
I am creating a custom workflow in Microsoft Dynamics CRM to automatically update a field when a record is saved.
A developer on a forum provided the following source code; but he is not responding to my questions.
public class SalesRepActivity2 : WorkFlowActivityBase
{
[Input("Sales Rep Name")]
public InArgument<string> SalesRepName { get; set; }
[Output("Sales Rep")]
[ReferenceTarget("systemuser")]
public OutArgument<EntityReference> SalesRep { get; set; }
[Output("IsSuccess")]
public OutArgument<bool> IsSuccess { get; set; }
[Output("Message")]
public OutArgument<string> Message { get; set; }
protected override void Execute(
CodeActivityContext activityContext,
IWorkflowContext workflowContext,
IOrganizationService CrmService,
ITracingService trace)
{
try
{
string salesRepName = SalesRepName.Get(activityContext);
if (string.IsNullOrWhiteSpace(salesRepName))
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "Sales Rep Name not provided");
}
var QEsystemuser = new QueryExpression("systemuser");
QEsystemuser.ColumnSet.AddColumns("salesrepname");
QEsystemuser.Criteria.AddCondition("salesrepname", ConditionOperator.Equal, salesRepName);
var results = CrmService.RetrieveMultiple(QEsystemuser);
if (results == null || !results.Entities.Any())
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "User with " + salesRepName + " not found");
return;
}
if (results.Entities.Count > 1)
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "Multiple users found with same name : " + salesRepName);
return;
}
IsSuccess.Set(activityContext, true);
SalesRep.Set(activityContext, results.Entities.Single().ToEntityReference());
}
catch (Exception ex)
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "An error occurred trying to find user : " + ex.Message);
}
}
I am trying to get the code to compile on my machine.
I installed the following NuGet packages, which resolved most of the errors:
Microsoft.Xrm.Sdk.Workflow.2015
Microsoft.Xrm.Sdk.2015
But my project cannot resolve the WorkFlowActivityBase class.
Is there a reference I should set or a NuGet package I should install to resolve this?
Thank you.
WorkFlowActivityBase is a custom base class that implements the CodeActivity (System.Activities) anyone can write, it's not an official Dynamics class. Yon can find dozen of classes lie that in the web.
Basically, you should use the CodeActivity. here as an example:
https://learn.microsoft.com/en-us/powerapps/developer/common-data-service/workflow/sample-create-custom-workflow-activity
The code you posted is not a good place for you to start because it makes heavy use of proprietary objects. Ziv has provided good information about extending the CodeActivity class but I do not recommend starting there. Instead read about how to develop custom workflow activities, and write a workflow using the base Microsoft classes so that you understand how they work:
https://learn.microsoft.com/en-us/powerapps/developer/common-data-service/workflow/workflow-extensions
Once you have some experience with creating custom workflows, and you understand the limitations of the base objects, then go back and implement something more fancy.
Here in an exaple from the documentation:
namespace Microsoft.Crm.Sdk.Samples
{
public sealed class SimpleSdkActivity : CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
//Create the tracing service
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
...
var systemUsers = service.RetrieveMultiple(QEsystemuser)
}
}
}
I looking for different validation style for forms when I create and update entities.
For Instance, when I create an "UserClass" object it requires an ID to define, but when I update, I do not need ID again, because it is defined by user at the creation step. I have lots of entity and I need to find most proper way.
For instance is this logical?
public interface RecordGroupValidator {
public void validateNew(RecordGroup recordGroup, Errors errors);
public void validateUpdate(RecordGroup recordGroup, Errors errors);
}
Validator :
public class RecordGroupValidatorImpl implements RecordGroupValidator {
#Autowired
RecordGroupService recordGroupService;
#Override
public void validateNew(RecordGroup recordGroup, Errors errors) {
if (!ValidationHandler.validText(recordGroup.getIds())) {
errors.rejectValue(ColumnIdentifier.COLUMN.Ids.name(), TextParameters.SERVLET_RESPONSE.InvalidParameter.getText());
}
if (!ValidationHandler.validText(recordGroup.getName())) {
errors.rejectValue(ColumnIdentifier.COLUMN.Name.name(), TextParameters.SERVLET_RESPONSE.InvalidParameter.getText());
}
if (recordGroup.getRecordGroupType() == null) {
errors.rejectValue(ColumnIdentifier.COLUMN.RecordGroupType.name(), TextParameters.SERVLET_RESPONSE.InvalidParameter.getText());
}
if (recordGroupService.idsExist(recordGroup.getIds())) {
errors.rejectValue(ColumnIdentifier.COLUMN.Ids.name(), TextParameters.SERVLET_RESPONSE.DuplicateEntry.getText());
}
if (recordGroupService.nameExist(recordGroup.getName())) {
errors.rejectValue(ColumnIdentifier.COLUMN.Name.name(), TextParameters.SERVLET_RESPONSE.DuplicateEntry.getText());
}
}
#Override
public void validateUpdate(RecordGroup recordGroup, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, ColumnIdentifier.COLUMN.Name.name(), TextParameters.SERVLET_RESPONSE.InvalidParameter.getText());
if (recordGroup.getRecordGroupType() == null) {
errors.rejectValue(ColumnIdentifier.COLUMN.Type.name(), TextParameters.SERVLET_RESPONSE.InvalidParameter.getText());
}
}
}
I think you should create two validation. One for create and one for update. This will create clever architecture. Because for now you have only one difference but in the future you can have more. In my opinion you should split them now.
We have a custom TraceListener implementation which only logs when a specific object (LogMessage) is received. This all works well when using directly with the Trace.Write(object) method.
Due to Performance reason, I want to separate the Listener, so all non-relevant Trace messages are not passed to the listener. Therefore I created a specific TraceSource whith only this listener attached.
Now I struggle to pass my custom log object (LogMessage) to the listener using the TraceSource. The TraceSource.TraceData(TraceEventType, int, object) always invokes the TraceListener.Write(string) method, not the TraceListener.Write(object) method.
Is there any way I can pass the custom object to the Listener using the TraceSource?
Sample code:
using System.Diagnostics;
namespace Sample
{
public class LogMessage
{
public byte[] Data { get; set; }
//...
}
public class Sample
{
public void Foo()
{
var ts = new TraceSource("Test");
var lm = new LogMessage();
//lm.Data = ...;
//this works: calls the Write(object) method in listener
Trace.Write(lm);
//this doesn't work: calls the Write(string) method in listener
ts.TraceData(TraceEventType.Information, 0, lm);
}
}
public class MyListener : TraceListener
{
public override void Write(string message)
{
//not in use
}
public override void WriteLine(string message)
{
//not in use
}
public sealed override void Write(object o)
{
if (o is LogMessage)
{
//do someting with the LogMessage
}
}
}
}
Thanks
Thomas
maybe it's too late for an answer but anyway :
By using a tool like JustDecompile you can easily see that TraceSource.TraceData uses TraceListener.TraceData method which itself basically calls WriteLine with object.ToString() for message.
So you'll have to override the ToString method for your class LogMessage in order to do as you want.
I'm using a class test that checks login entity that is being done correctly, but an error occurs that does not seem to return the query in the database, but the application developed in ASP.NET MVC 3 Code First query returns data, I would to know what is wrong and what can be done to solve it.
Upon return of the query gives the following message in the variable:
"Enumeration yielded no results"
Test Method:
[TestMethod()]
public void efetuarLoginTest()
{
EntidadeRepository target = new EntidadeRepository();
string cnpj = "12345678";
string senha = "lalado";
Entidade expected = null; // TODO: Initialize to an appropriate value
Entidade actual;
actual = target.efetuarLogin(cnpj, senha);
Assert.AreNotEqual(expected, actual);
}
Method repository of the entity with the task of returning to the login query:
public Entidade efetuarLogin(string cnpj, string senha)
{
var consulta = from usu in bd.Entidades
where usu.cnpj == cnpj && usu.senha == senha
select usu;
if (consulta.Count() > 0)
{
Entidade e = new Entidade();
e.id_entidade = consulta.First().id_entidade;
e.razao_social = consulta.First().razao_social;
e.cnpj = consulta.First().cnpj;
e.senha = consulta.First().senha;
return e;
}
else
{
return null;
}
}
Class persistence database using the Entity Framework 4.1:
internal class BancoDados: DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingEntitySetNameConvention>();
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
public DbSet<Entidade> Entidades { get; set; }
public DbSet<Estado> Estados { get; set; }
public DbSet<Administrador> Administradores { get; set; }
public DbSet<Leilao> Leiloes { get; set; }
public DbSet<Lance> Lances { get; set; }
}
Thank You.
for us, this kind of an error was generated because of the right connection string not passed to the EF. If you are using NUnit, NUnit doesn't use your app.config or web.config, you would have to create your assembly.dll.config or nunit project.config. Please check NUnit documentation for usage of config files.
You can verify the connection string passed to NUnit, by examining, DbContext.Database and its properties in debug mode/
Checking your config values, should fix your problem.
I would imagine
if (consulta.Count() > 0)
is throwing the error?
You could change it to
if (consulta != null && consulta.Count() > 0)