Acumatica - Add Reports dropdown to Kit Assembly Screen - report

I have been trying to add a Reports dropdown to the Kit Assembly screen (IN307000). We have custom reports that are based on the KitInventoryID that will be generated to print a tag essentially and these reports need to be added to the actions of the screen. I noticed that there is normally a transfer in most Report screens that will be used to transfer data so I did write my own statement at the top. Here is what I have so far:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.IN.Overrides.INDocumentRelease;
using PX.Objects.GL;
using PX.Objects.CM;
using System.Diagnostics;
using PX.Objects;
using PX.Objects.IN;
namespace PX.Objects.IN
{
public class KitAssemblyEntry_Extension:PXGraphExtension<KitAssemblyEntry>
{
public PXSelect<INKitRegister, Where<INKitRegister.docType, Equal<Current<INKitRegister.docType>>, And<INKitRegister.kitInventoryID, Equal<Current<INKitRegister.kitInventoryID>>>>> transfer;
public override void Initialize()
{
Report.AddMenuAction(MasterTag);
Report.MenuAutoOpen = true;
}
#region Event Handlers
public PXAction<INKitRegister> Report;
[PXButton]
[PXUIField(DisplayName = "Print Tag", MapEnableRights = PXCacheRights.Select)]
protected void report()
{ }
public PXAction<INKitRegister> MasterTag;
[PXUIField(DisplayName = "Sample/Value Tag", MapEnableRights = PXCacheRights.Select)]
[PXLookupButton]
public virtual IEnumerable masterTag(PXAdapter adapter)
{
INKitRegister doc = Base.transfer.Current;
if (doc != null)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters["DocType"] = this.transfer.Current.DocType;
parameters["ItemNumber"] = this.transfer.Current.KitInventoryID.ToString();
throw new PXReportRequiredException(parameters, "IN610004", "Sample/Value Tag");
}
}
#endregion
}
}
However, when I try to publish I get this error:
Building directory '\WebSiteValidationDomain\App_RuntimeCode\'.
\App_RuntimeCode\KitAssemblyEntry.cs(39): error CS1061: 'PX.Objects.IN.KitAssemblyEntry' does not contain a definition for 'transfer' and no extension method 'transfer' accepting a first argument of type 'PX.Objects.IN.KitAssemblyEntry' could be found (are you missing a using directive or an assembly reference?)
\App_RuntimeCode\KitAssemblyEntry.cs(39): error CS1061: 'PX.Objects.IN.KitAssemblyEntry' does not contain a definition for 'transfer' and no extension method 'transfer' accepting a first argument of type 'PX.Objects.IN.KitAssemblyEntry' could be found (are you missing a using directive or an assembly reference?)
I have also tried changing the INKitRegister doc = Base.transfer.Current;to INKitRegister doc = Base.Document.Current; but get this error:
\App_RuntimeCode\KitAssemblyEntry.cs(37): error CS0161: 'PX.Objects.IN.KitAssemblyEntry_Extension.masterTag(PX.Data.PXAdapter)': not all code paths return a value
\App_RuntimeCode\KitAssemblyEntry.cs(37): error CS0161: 'PX.Objects.IN.KitAssemblyEntry_Extension.masterTag(PX.Data.PXAdapter)': not all code paths return a value

Here is the fixed coded and it is working properly.
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.IN.Overrides.INDocumentRelease;
using PX.Objects.GL;
using PX.Objects.CM;
using System.Diagnostics;
using PX.Objects;
using PX.Objects.IN;
namespace PX.Objects.IN
{
public class KitAssemblyEntry_Extension:PXGraphExtension<KitAssemblyEntry>
{
public PXSelect<INKitRegister, Where<INKitRegister.docType, Equal<Current<INKitRegister.docType>>, And<INKitRegister.kitInventoryID, Equal<Current<INKitRegister.kitInventoryID>>>>> transfer;
public override void Initialize()
{
Report.AddMenuAction(MasterTag);
Report.MenuAutoOpen = true;
}
#region Event Handlers
public PXAction<INKitRegister> Report;
[PXButton]
[PXUIField(DisplayName = "Print Tag", MapEnableRights = PXCacheRights.Select)]
protected void report()
{ }
public PXAction<INKitRegister> MasterTag;
[PXUIField(DisplayName = "Sample/Value Tag", MapEnableRights = PXCacheRights.Select)]
[PXLookupButton]
public virtual IEnumerable masterTag(PXAdapter adapter)
{
INKitRegister doc = Base.Document.Current;
if (doc != null)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters["DocType"] = this.transfer.Current.DocType;
parameters["ItemNumber"] = this.transfer.Current.KitInventoryID.ToString();
throw new PXReportRequiredException(parameters, "IN610004", "Sample/Value Tag");
}
return adapter.Get();
}
#endregion
}
}

Related

NServicebus not unable to resolve service for interface in handler

I'm trying to build my first NserviceBus application, but I cannot get it to work. The message arrives on the "backend" but the handler uses DI and NServicebus claims it cannot find the service for the interface. But the code was lifted directly from the examples. I'm missing something and I cannot figure it out.
The Error:
dbug: NServiceBus.LoadHandlersConnector[0]
Processing message type: Messages.JobStartCommand
Message headers:
NServiceBus.MessageId : 0044f261-e3b3-4287-b6f0-ad7400ef43cb
NServiceBus.MessageIntent : Send
NServiceBus.ConversationId : bb4f276f-63fe-450b-b234-ad7400ef43cd
NServiceBus.CorrelationId : 0044f261-e3b3-4287-b6f0-ad7400ef43cb
NServiceBus.ReplyToAddress : ClientUI
NServiceBus.OriginatingMachine : L19002992
NServiceBus.OriginatingEndpoint : ClientUI
$.diagnostics.originating.hostid : e1fecb2b72b8185e47341bb4dfb37dd7
NServiceBus.ContentType : text/xml
NServiceBus.EnclosedMessageTypes : Messages.JobStartCommand, Messages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
NServiceBus.Version : 7.5.0
NServiceBus.TimeSent : 2021-07-29 14:31:08:228497 Z
NServiceBus.Retries : 3
NServiceBus.Retries.Timestamp : 2021-07-29 14:31:40:397277 Z
Handlers to invoke:
Extractor.JobStartHandler
Extractor.JobStartHandler
info: NServiceBus.RecoverabilityExecutor[0]
Immediate Retry is going to retry message '0044f261-e3b3-4287-b6f0-ad7400ef43cb' because of an exception:
System.InvalidOperationException: Unable to resolve service for type 'IExtract' while attempting to activate 'Extractor.JobStartHandler'.
at Microsoft.Extensi
My backend program.cs
using Microsoft.Extensions.Hosting;
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NServiceBus;
using System.Threading.Tasks;
using Messages;
using Extractor;
namespace ExtractorOsiris
{
class Program
{
static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var builder = Host.CreateDefaultBuilder(args);
builder.UseWindowsService();
//builder.UseMicrosoftLogFactoryLogging();
builder.ConfigureLogging((ctx, logging) =>
{
logging.AddConfiguration(ctx.Configuration.GetSection("Logging"));
//logging.AddEventLog();
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Debug);
});
#region back-end-use-nservicebus
builder.UseNServiceBus(ctx =>
{
var endpointConfiguration = new EndpointConfiguration("Sample.Extractor");
endpointConfiguration.UseTransport<LearningTransport>();
var transport = endpointConfiguration.UseTransport<LearningTransport>();
transport.Routing().RouteToEndpoint(typeof(ProcessObjectCommand), "Sample.Processor");
endpointConfiguration.DefineCriticalErrorAction(OnCriticalError);
return endpointConfiguration;
});
#endregion
#region back-end-register-service
builder.ConfigureServices(services =>
{
services.AddSingleton<IExtract, ExtractOsiris>();
});
#endregion
return builder;
}
private static Task OnCriticalError(ICriticalErrorContext arg)
{
throw new NotImplementedException();
}
}
}
The Interface
using Newtonsoft.Json.Linq;
using NServiceBus;
using System;
using System.Threading.Tasks;
namespace Extractor
{
public interface IExtract
{
Task<JArray> Extract(string #object, DateTime deltaTime);
}
}
The handler
using System.Threading.Tasks;
using Messages;
using Newtonsoft.Json.Linq;
using NServiceBus;
namespace Extractor
{
#region back-end-handler
public class JobStartHandler : IHandleMessages<JobStartCommand>
{
private readonly IExtract extractor;
public JobStartHandler(IExtract extractor)
{
this.extractor = extractor;
}
public async Task Handle(JobStartCommand message, IMessageHandlerContext context)
{
Task<JArray> result = extractor.Extract("Medewerkers", message.DeltaTime);
await result;
JArray test = result.Result;
foreach (JObject x in test)
{
// send the object to be processed.
//await context.Send(new ProcessObjectCommand(x.ToString()));
}
}
}
#endregion
}
The implementation of the interface
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Extractor;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NServiceBus;
namespace ExtractorOsiris
{
public class ExtractOsiris : IExtract
{
private readonly ILogger logger;
public ExtractOsiris(ILogger<ExtractOsiris> logger)
{
this.logger = logger;
}
public Task<JArray> Extract(string #object, DateTime deltaTime)
{
logger.LogInformation($"getting {#object} for delta time {deltaTime}");
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://xx.yy");
WebResponse response = request.GetResponse();
JObject temp = JObject.Load(new JsonTextReader(new StreamReader(response.GetResponseStream())));
return Task<JArray>.FromResult(temp["items"] as JArray);
}
}
}
I know the code ain't pretty, but it's pure quick and dirty testing code.
I cleaned out the offending interface from the code and still got the error on an interface that was not even there anymore. I removed the bin folder and build everything back up step by step. Stupid thing is, source control says I am back where I started, without changes. And it just works....
So must have bin something stupid with VS2019. Sorry to anyone who's time I wasted

What is the correct model binding architecture for this situation?

I'm replacing some old webservice code with WebApi, and I've got a situation where the code used to do something like this:
If Request.QueryString("value") = 1 Then
{do first action}
Else
{do second action}
End If
Each action is totally different, and each has an independent set of other query string parameters.
In my new version, I'm modelling this as:
Public Function FirstAction(model as FirstActionModel) As HttpResponseMessage
and
Public Function SecondAction(model as SecondActionModel) As HttpResponseMessage
The catch is that the incoming request is going to just call /api/actions?actiontype=1&params... or /api/actions?actiontype=2&params... and the params are different.
I want to be able to route a request with actiontype=1 to FirstAction, and actiontype=2 to SecondAction. But I can't use routing, because the important value is in the query string, not the path.
How can I do this?
As i've mentioned in comments you can use IHttpActionSelector to achieve this. But instead of implementing interface directly you can inherit from default implementation.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Controllers;
namespace WebApplication1
{
public class CustomHttpActionSelector : ApiControllerActionSelector
{
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var urlParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query);
var actionType = urlParam["actiontype"];
if (actionType == null)
return base.SelectAction(controllerContext);
MethodInfo methodInfo;
if (actionType.ToString() == "1")
methodInfo = controllerContext.ControllerDescriptor.ControllerType.GetMethod("Action1");
else
methodInfo = controllerContext.ControllerDescriptor.ControllerType.GetMethod("Action2");
return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, methodInfo);
}
}
}
And to register it you need to add following line to your WebApiConfig.cs file:
config.Services.Replace(typeof(IHttpActionSelector), new CustomHttpActionSelector());
In your controller you than add two methods Action1 and Action2:
public string Action1(string param)
{
return "123";
}
public string Action2(string param)
{
return "345";
}

Unable to create component using Coreservice

I am trying to create component using coreservice using the below code, and when i execute the exe, am getting the error "unable to find the uuid:""64c7e56a-161d-4698-a76b-7fd96227948d:Content".
I have opened the schema which am linking to this component, and i seen this UUID over there also.
as of now am just trying to create a component by providing the folder, schema, title as hard corded.
if you can guide me how to add field value also in component, that would be great. (For example assume that i have a field "Text" in my schema which am linking to this component, and i want to add "This is the Text" in this field of my component using the same program.
can you please help me out on this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DctmToSDLMigration.SDLCoreServiceReference;
namespace DctmToSDLMigration
{
class Program
{
static DctmToSDLMigration.SDLCoreServiceReference.SessionAwareCoreService2010Client client = new SessionAwareCoreService2010Client();
static ReadOptions readoptions = new ReadOptions();
static void CreateComponent()
{
try
{
string TargetFolderTcmId = "tcm:148-1263-2";
string LinkSchemaTcmId = "tcm:148-11460-8";
ComponentData CurrentMigrationComponent = client.GetDefaultData(ItemType.Component, TargetFolderTcmId) as ComponentData;
LinkToSchemaData SchemaToUse = new LinkToSchemaData();
SchemaToUse.IdRef = LinkSchemaTcmId.ToString();
CurrentMigrationComponent.Schema = SchemaToUse ;
CurrentMigrationComponent.Title = "Test component";
client.Create(CurrentMigrationComponent, readoptions);
Console.WriteLine(CurrentMigrationComponent.Id);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
static void Main(string[] args)
{
CreateComponent();
}
}
}
You need to set the Content Property of the Component.
XmlDocument doc = new XmlDocument();
doc.LoadXml(string.Format(#"<Content xmlns='{0}'><Test>Hello</Test></Content>", SchemaToUse.NamespaceUri));
CurrentMigrationComponent.Content = doc.DocumentElement;

Can not call Public List from App_Code folder in Web Form

So here's my predicament. I'm writing a custom, one-off content management system, and I can not for the life of me getting this method to work correctly. What I want to do is create a laundry list worth of methods in separate folders and call them as I need them on whichever web forms I want to call them on.
I created a WebApp and created a folder inside of the app called App_Code. Inside of App_Code, there is a public class called "TestimonialService". Here it is:
/******************** TESTIMONIAL SERVICE ****************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlueTreeSecurity.App_Code.Data;
namespace BlueTreeSecurity.App_Code.Testimonials
{
public class TestimonialService
{
private readonly CMSObjectContext _context;
public TestimonialService(CMSObjectContext context)
{
this._context = context;
}
#region methods
/// <summary>
/// Gets all testimonials
/// </summary>
/// <returns>testimonial collection</returns>
public List<Testimonial> GetAllTestimonials()
{
var query = from t in _context.Testimonials
orderby t.DisplayOrder ascending
select t;
if (query.Count() > 0)
{
var testimonial = query.ToList();
return testimonial;
}
else
{
return null;
}
}
#endregion
}
}
Then on the actual aspx.cs page I call said function like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using BlueTreeSecurity.App_Code;
using BlueTreeSecurity.App_Code.Data;
using BlueTreeSecurity.App_Code.Testimonials;
namespace BlueTreeSecurity
{
public partial class Testimonials : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.Page.Title = "Testimonials | ...";
Bind_Data();
}
protected void Bind_Data()
{
/** when i try to use intellisense here it's not recognized. **/
var testimonials = TestimonialService.GetAllTestimonials();
rptTestimonials.DataSource = testimonials;
rptTestimonials.DataBind();
}
}
}
The exact error spat back is this:
Error 1
An object reference is required for the non-static field, method, or property
'BlueTreeSecurity.App_Code.Testimonials.TestimonialService.GetAllTestimonials()'
Anything would be appreciated, guys. I'm ripping my hair out here.
Here's the Project structure
- Blue Tree Security (main project)
- App_Code
+ Data
+ Testimonials
+ TestimonialService.cs
Rest of the .aspx, .aspx.cs, and .ascx files.
If i'm not totally misinterpreting here, the error message you are getting is telling you what the problem is. Make GetAllTestimonials() static or instantiate a TestimonialService instance.
protected void Bind_Data()
{
var testimonialService = new TestimonialService(yourContextObect);
var testimonials = testimonialService.GetAllTestimonials();
rptTestimonials.DataSource = testimonials;
rptTestimonials.DataBind();
}

Populating a Telerik Grid using ViewModel (MVC3)

Ok, this is a really newbie question but I am stumped.
I am trying to use a ViewModel to get my data from an entity object and populate the telerik mvc grid.
At this point I am a bit confused and need your help.
I understand the error message but I am not sure how I need to fix this since I am really new to MVC.
----ERROR----
Error 1 Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IQueryable'. An explicit conversion exists (are you missing a cast?) ProjectRepository.cs 23 20 MvcMyAPP
I have this viewmodel:
--VIEWMODEL--
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI.WebControls;
namespace mvcMyModel.ViewModels
{
public class ProjectViewModel
{
public IQueryable<mvcMyAPP.Models.ProjectRepository> ProjectList
{
get;
set;
}
}
}
--CONTROLLER--
namespace MvcMyAPP.Controllers
{
public class HomeController : Controller
{
// GET: /Home/
ProjectRepository Repository = new ProjectRepository();
public ActionResult Index()
{
ProjectViewModel objProjectViewModel = new ProjectViewModel();
objProjectViewModel.ProjectList = Repository.GetProjects();
return View(objProjectViewModel);
return View();
}
}
}
----REPOSITORY (MODEL)-----
namespace mvcMyAPP.Models
{
public class ProjectRepository
{
mvcMyAPP.Models.MYEntities MYDB = new MYEntities();
//Fetching data from table
public IQueryable<mvcMyAPP.ViewModels.ProjectViewModel> GetProjects()
{
var vProjects = (from tblProjects in MYDB.Projects
select tblProjects);
return vProjects;
}
}
---GRID---
#{Html.Telerik().Grid(Model.ProjectList)
.Name(
"Grid")
.Pageable()
.Sortable()
.Filterable()
.Groupable()
.Render();
}
You don't need the second return View() in the controller, but that isn't causing any problems.
You might try putting a cast on the return variable from your repository so it is returning the type specified in return:
// return vProjects;
// cast the return variable to return type
return (IQueryable<mvcMyAPP.ViewModels.ProjectViewModel>)vProjects;
I highly recommend Microsoft site for learning MVC, they have a great starting point for learning MVC.
http://www.asp.net/mvc

Resources