.NET Core - SerializerSettings not being applied - json

Startup.cs
services.AddMvc().AddJsonOptions(options => {
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});
Random class
JsonConvert.SerializeObject(configItem)
SerializerSettings are not being applied -> null values are not ignored.

Inside startup.cs:
JsonConvert.DefaultSettings = () => {
return new JsonSerializerSettings() {
NullValueHandling = NullValueHandling.Ignore
};
};
To apply global JsonConvert settings.

Related

JSON.stringify - downcasting an object

Is there a way to tell the stringify method to convert an object to a primitive datatype?
class Bar {
constructor() {
this.name = 'bar';
}
}
const obj = {foo: new Bar};
JSON.stringify(obj);
// output: '{foo: {name: 'bar'}}'
// wanted output: '{foo:'bar'}'
I've tried overriding toSting and valueOf methods but with no results
Bar.prototype.toString = function() {
return this.name;
}
Bar.prototype.valueOf = function() {
return this.name;
}
Add toJSON prototype method in Bar class.
Bar.prototype.toJSON = function() {
return this.name;
}

Viewer after ver. 7.37 -- use setAggregatedProperties

I am using a custom property panel.
There is any sample of how to replace older "setProperties" with new "setAggregatedProperties" in the viewer?
Thanks in advance
Yes, this sample is using it: https://forge-extensions.autodesk.io/?extension=CustomPropertiesExtension
Source code: https://github.com/Autodesk-Forge/forge-extensions/blob/master/public/extensions/CustomPropertiesExtension/contents/main.js
class CustomPropertyPanel extends Autodesk.Viewing.Extensions.ViewerPropertyPanel {
constructor (viewer, options) {
super(viewer, options);
this.properties = options.properties || {};
}
setAggregatedProperties(propertySet) {
Autodesk.Viewing.Extensions.ViewerPropertyPanel.prototype.setAggregatedProperties.call(this, propertySet);
// add your custom properties here
const dbids = propertySet.getDbIds();
dbids.forEach(id => {
var propsForObject = this.properties[id.toString()];
if (propsForObject) {
for (const groupName in propsForObject) {
const group = propsForObject[groupName];
for (const propName in group) {
const prop = group[propName];
this.addProperty(propName, prop, groupName);
}
}
}
});
}
};

Download CSV in Mezzio Framework (Zend/Laminas)

In Mezzion Framework I have the next Handler:
<?php
namespace Bgc\Handler;
use App\Service\GenerateReportToCSV;
use Bgc\Queue\BGCQueueManager;
use Laminas\Diactoros\Response\TextResponse;
use League\Csv\Writer;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class DownloadBgcReportHandler implements RequestHandlerInterface
{
protected $bgcQManager;
protected $reportToCSV;
public function __construct(BGCQueueManager $bgcQManager, $reportToCSV)
{
$this->bgcQManager = $bgcQManager;
$this->reportToCSV = $reportToCSV;
}
public function handle(ServerRequestInterface $request): TextResponse
{
$queryParams = $request->getQueryParams();
$params = [];
if (isset($queryParams['startDate'])) {
$starDate = new \DateTime($queryParams['startDate']);
$params['startDate'] = $starDate->modify('midnight');
}
if (isset($queryParams['startDate'])) {
$endDate = new \DateTime($queryParams['endDate']);
$params['endDate'] = $endDate->modify('tomorrow');
}
$itemsBGC = $this->bgcQManager->getDataToDownload($params);
$time = time();
$fileName = "bgc-report-$time.csv";
$csv = Writer::createFromFileObject(new \SplFileObject());
$csv->insertOne($this->reportToCSV->getHeadingsBGC());
foreach ($itemsBGC as $item) {
$csv->insertOne($item);
}
return new TextResponse($csv->getContent(), 200, [
'Content-Type' => 'text/csv',
'Content-Transfer-Encoding' => 'binary',
'Content-Disposition' => "attachment; filename='$fileName'"
]);
}
}
I have the below error:
Whoops\Exception\ErrorException: Declaration of Bgc\Handler\DownloadBgcReportHandler::handle(Psr\Http\Message\ServerRequestInterface $request): Laminas\Diactoros\Response\TextResponse must be compatible with Psr\Http\Server\RequestHandlerInterface::handle(Psr\Http\Message\ServerRequestInterface $request): Psr\Http\Message\ResponseInterface in file /home/peter/proyectos/revelations-thena-api/src/Bgc/src/Handler/DownloadBgcReportHandler.php on line 20
I don't know, to create a downloable file. The hadbler works fine with Json. I tried to change from ResponseInterface to TextResponse.
How can I download file CSV?
Thank you
The error you received is telling you that your method signature is not compliant to interface's method signature.
RequestHandlerInterface:
interface RequestHandlerInterface
{
public function handle(ServerRequestInterface $request): ResponseInterface;
}
As you see, the signature states that an object of type ResponseInterface is returned.
You modified the signature:
class DownloadBgcReportHandler implements RequestHandlerInterface
{
public function handle(ServerRequestInterface $request): TextResponse;
}
The signature must be the same, but then you can return the TextResponse without problem (since it extends Laminas\Diactoros\Response, which implements Psr\Http\Message\ResponseInterface)
Just change that and it will works :)
You have modified you handle method, so right now you aren't fulfilling the requirements of the RequestHandlerInterface
Replace the return value for the handler with ResponseInterface enforced in the interface: RequestHandlerInterface
so i think you are best helped with:
<?php
namespace Bgc\Handler;
use App\Service\GenerateReportToCSV;
use Bgc\Queue\BGCQueueManager;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\Stream;
use League\Csv\Writer;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class DownloadBgcReportHandler implements RequestHandlerInterface
{
protected $bgcQManager;
protected $reportToCSV;
public function __construct(BGCQueueManager $bgcQManager, $reportToCSV)
{
$this->bgcQManager = $bgcQManager;
$this->reportToCSV = $reportToCSV;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$queryParams = $request->getQueryParams();
$params = [];
if (isset($queryParams['startDate'])) {
$starDate = new \DateTime($queryParams['startDate']);
$params['startDate'] = $starDate->modify('midnight');
}
if (isset($queryParams['startDate'])) {
$endDate = new \DateTime($queryParams['endDate']);
$params['endDate'] = $endDate->modify('tomorrow');
}
$itemsBGC = $this->bgcQManager->getDataToDownload($params);
$time = time();
$fileName = "bgc-report-$time.csv";
// $csv = Writer::createFromFileObject(new \SplFileObject());
// $csv->insertOne($this->reportToCSV->getHeadingsBGC());
$csv = Writer::createFromString($this->reportToCSV->getHeadingsBGC());
foreach ($itemsBGC as $item) {
$csv->insertOne($item);
}
$body = new Stream($csv->getContent());
return new Response($body, 200, [
'Cache-Control' => 'must-revalidate',
'Content-Disposition' => 'attachment; filename=' . $fileName,
'Content-Length' => strval($body->getSize()),
'Content-Type' => 'text/csv',
'Content-Transfer-Encoding' => 'binary',
'Expires' => '0',
'Pragma' => 'public',
]);
}
}
PS: i have commented the 2 lines in which an empty new \SplFileObject() was used, because the required param $filename was empty (and i did not want to make a decision there) and added a line with Writer::createFromString().

Swagger not working (rather exception is thrown) after migrating project from .net core 2.2 to 3.0 preview-7

I have just migrated my project from .net core 2.2 to 3.0 preview 7. I am using Swashbuckle.AspNetCore (v4.0.1) in it. This is my startup class.
public class Startup
{
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration["ConnectionStrings:ConnectionStringAzureSQL"]));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddApplicationInsightsTelemetry();
services.AddLocalization(options => options.ResourcesPath = #"Resources");
services.AddMemoryCache();
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US")
};
options.DefaultRequestCulture = new RequestCulture("en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "GetAJobToday", Description = "GetAJobTodayAPIs" });
var xmlPath = AppDomain.CurrentDomain.BaseDirectory + #"PlatformAPI.xml";
c.IncludeXmlComments(xmlPath);
c.AddSecurityDefinition("Bearer",
new ApiKeyScheme
{
In = "header",
Description = "Please enter token into the field",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{"Bearer", new string[] { }},
});
});
services.AddSingleton<ITelemetryInitializer, HttpContextItemsTelemetryInitializer>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseRouting();
app.UseMiddleware<ApiLoggingMiddleware>();
app.UseHttpsRedirection();
app.UseRequestLocalization(app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapControllerRoute("default", "{controller=Auth}/{action=RequestVerificationCode}/{id?}");
});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "GetAJobToday");
});
}
}
But it is throwing this exception when I run it:
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Swashbuckle.AspNetCore.Swagger.ISwaggerProvider Lifetime: Transient ImplementationType: Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator': Failed to compare two elements in the array.) (Error while validating the service descriptor 'ServiceType: Swashbuckle.AspNetCore.SwaggerGen.ISchemaRegistryFactory Lifetime: Transient ImplementationType: Swashbuckle.AspNetCore.SwaggerGen.SchemaRegistryFactory': Failed to compare two elements in the array.)
Upgrading Swashbuckle.AspNetCore and Swashbuckle.AspNetCore.Filters to v 5.0.0-rc2 solved the problem.
Upgrading Swashbuckle.AspNetCore to the latest version v 5.0.0-rc4 solved the problem.

Detect when bind occurs in mvvmcross

Hi i need to intercept when bind occur in mvvmcross project.
I have my MvxCollectionViewCell that i bind:
public ProjectsCollectionCell (IntPtr handle)
: base (string.Empty, handle)
{
this.DelayBind(() => {
var set = this.CreateBindingSet<ProjectsCollectionCell, ViewItem>();
set.Bind (lblTitle).To (prj => prj.MnemonicId);
set.Bind (lblDescription).To (prj => prj.Description);
set.Bind(imgPhoto).For (s => s.Image).WithConversion("ImageArray").To(prj => prj.Image);
set.Apply();
if (imgPhoto.Image != null) {
this.imgPhoto.Layer.RasterizationScale = UIScreen.MainScreen.Scale;
this.imgPhoto.Layer.ShouldRasterize = true;
this.imgPhoto.Layer.BorderWidth = 10;
this.imgPhoto.Layer.BorderColor = UIColor.White.CGColor;
this.imgPhoto.Layer.CornerRadius = 8f;
this.imgPhoto.Layer.MasksToBounds = true;
this.imgPhoto.Layer.Position = new PointF(imgPhoto.Frame.Left - 80, imgPhoto.Frame.Bottom);
this.imgPhoto.Transform = CGAffineTransform.MakeRotation(-0.05f);
};
});
}
i want to intercept when the content of the 'imgPhoto' change.
Is there an event to subscribe?
Could you suggest me how to do this?
If you need to detect when the Image on your cell's DataContext changes, then one way to do this is to add the property to your cell and to bind that property to your DataContext - e.g.
private byte[] _bytes;
public byte[] Bytes
{
get { return _bytes; }
set
{
_bytes = value;
// your code here...
}
}
public ProjectsCollectionCell (IntPtr handle)
: base (string.Empty, handle)
{
this.DelayBind(() => {
var set = this.CreateBindingSet<ProjectsCollectionCell, ViewItem>();
set.Bind(_hook).For(h => h.CurrentSource);
set.Bind (lblTitle).To (prj => prj.MnemonicId);
set.Bind (lblDescription).To (prj => prj.Description);
set.Bind(this).For(s => s.Bytes).WithConversion("ImageArray").To(prj => prj.Image);
set.Apply();
// etc
});
}
As an alternative, you might also want to consider subclassing whatever type imgPhoto is and providing a new property on that object. For an example of this approach, see the AnimatingText properties in http://slodge.blogspot.co.uk/2013/07/n33-animating-data-bound-text-changes.html