问:
Not posting data to an action with MVC(HTTP 415)
I'm looking to send the following fields to a MVC action

public class AddProductViewModel
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public int Quantity { get; set; }
    public double Price { get; set; }
    public bool Enabled { get; set; }
    public List<CategorySelectModel> Categories { get; set; } = new List<CategorySelectModel>();
    public List<IFormFile> Photos { get; set; } = new List<IFormFile>();
}
```
<p>CategorySelectModel:</p>
<pre class="lang-cs prettyprint-override"><code>
    public string CategoryId { get; set; }
    public string CategoryName { get; set; }

</code>```

and I haved used what i believe represents the actual json data...but I dont get why it isnt posting the data to the action
here is the js code where I have serialized the data and send to the controller

function SubmitProducts(element)
{
    element.preventDefault();

    let ulContainer = document.getElementById("dropDownAndSel").getElementsByTagName('ul')[0];

    var Categories = [];
    let x = document.getElementById("dropDownCategories");
    for (let i = 0; i < x.children.length; i++) {
        if (x.options[i].selected) {
           let CategoryName = x.options[i].innerHTML;
            let CategoryId = x.children[i].value;
            let dropdownItems = { CategoryId, CategoryName };

            if (!Categories.includes(dropdownItems)) {

                Categories.push(dropdownItems);
            }
        }
    }
    let pId = document.getElementById('pId').value;
    let ProductId = pId;
    let ProductName = document.getElementById('ProductName').value;
    if (!ProductName || ProductName.length ==0) {
        alert('ProdutName cannot be null or empty');
        return;
    }
    let priceStr = document.getElementById('productPriceId').value;
    if (!priceStr || priceStr.length == 0) {
        alert('Price cant be empty')
        return;
    }
    let Price = parseFloat(priceStr);

    let QuantityStr = document.getElementById('qtyNum').value;
    if (!QuantityStr || QuantityStr.length==0) {
        alert('Quantity cant be empty');
        return;
    }
    let Quantity = parseInt(QuantityStr);

    var formData = new FormData();

    let filesContainer = document.getElementById('photoProduct_0');
    for (let i = 0; i < filesContainer.files.length; i++) {
        formData.append('model.Photos', filesContainer.files[i], filesContainer.files[i].name);
    }

    formData.set('model.ProductId', ProductId);
    formData.set('model.ProductName', ProductName);
    formData.set('model.Price', Price);
    formData.set('model.Quantity', Quantity);
    formData.set('model.Categories', JSON.stringify(Categories));

    $.ajax({
        url: '/' + 'Product' + '/' + 'AddProduct',
        type: 'POST',
        contentType: false,
        processData: false,
        data: formData,
        success: console.log('success'),

    });
}
```
<p>Here is the action signature:</p>
<pre class="lang-cs prettyprint-override"><code>[HttpPost]
public async Task<IActionResult> AddProduct([FromBody] AddProductViewModel model)
</code>```

答:
Code above post FormData data. Therefore, the AddProductViewModel parameter should be bound using form-data in the request body:

```<code>[HttpPost]
public async Task<IActionResult> AddProduct([FromForm] AddProductViewModel model)
</code>```

Reference to the following post: ASP.NET Core form POST results in a HTTP 415 Unsupported Media Type response

Body:
I'm looking to send the following fields to a MVC action

public class AddProductViewModel
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public int Quantity { get; set; }
    public double Price { get; set; }
    public bool Enabled { get; set; }
    public List<CategorySelectModel> Categories { get; set; } = new List<CategorySelectModel>();
    public List<IFormFile> Photos { get; set; } = new List<IFormFile>();
}

CategorySelectModel:

    public string CategoryId { get; set; }
    public string CategoryName { get; set; }

and I haved used what i believe represents the actual json data...but I dont get why it isnt posting the data to the action
here is the js code where I have serialized the data and send to the controller

function SubmitProducts(element)
{
    element.preventDefault();

    let ulContainer = document.getElementById("dropDownAndSel").getElementsByTagName('ul')[0];

    var Categories = [];
    let x = document.getElementById("dropDownCategories");
    for (let i = 0; i < x.children.length; i++) {
        if (x.options[i].selected) {
           let CategoryName = x.options[i].innerHTML;
            let CategoryId = x.children[i].value;
            let dropdownItems = { CategoryId, CategoryName };

            if (!Categories.includes(dropdownItems)) {

                Categories.push(dropdownItems);
            }
        }
    }
    let pId = document.getElementById('pId').value;
    let ProductId = pId;
    let ProductName = document.getElementById('ProductName').value;
    if (!ProductName || ProductName.length ==0) {
        alert('ProdutName cannot be null or empty');
        return;
    }
    let priceStr = document.getElementById('productPriceId').value;
    if (!priceStr || priceStr.length == 0) {
        alert('Price cant be empty')
        return;
    }
    let Price = parseFloat(priceStr);

    let QuantityStr = document.getElementById('qtyNum').value;
    if (!QuantityStr || QuantityStr.length==0) {
        alert('Quantity cant be empty');
        return;
    }
    let Quantity = parseInt(QuantityStr);

    var formData = new FormData();

    let filesContainer = document.getElementById('photoProduct_0');
    for (let i = 0; i < filesContainer.files.length; i++) {
        formData.append('model.Photos', filesContainer.files[i], filesContainer.files[i].name);
    }

    formData.set('model.ProductId', ProductId);
    formData.set('model.ProductName', ProductName);
    formData.set('model.Price', Price);
    formData.set('model.Quantity', Quantity);
    formData.set('model.Categories', JSON.stringify(Categories));

    $.ajax({
        url: '/' + 'Product' + '/' + 'AddProduct',
        type: 'POST',
        contentType: false,
        processData: false,
        data: formData,
        success: console.log('success'),

    });
}

Here is the action signature:

[HttpPost]
public async Task<IActionResult> AddProduct([FromBody] AddProductViewModel model)

Body:
Code above post FormData data. Therefore, the AddProductViewModel parameter should be bound using form-data in the request body:

[HttpPost]
public async Task<IActionResult> AddProduct([FromForm] AddProductViewModel model)

Reference to the following post: ASP.NET Core form POST results in a HTTP 415 Unsupported Media Type response


来源: stackexchange

问:
How to make an Application Insights kusto query sort correctly on performanceBucket?
Is there a way to make an Application Insights kusto query sort on performanceBucket 'correctly', i.e. on bucket duration? When I summarize or sort using performanceBucket and don't specify a sort I get something like this (note for example that 1-3sec is not adjacent to 3-7sec):

If I add a sort by performanceBucket it's done alphanumerically:

I want it to be in this order (or the reverse of it)

<250ms

250ms-500ms

500ms-1sec

1sec-3sec

3sec-7sec

7sec-15sec

15sec-30sec

30sec-1min

1min-2min

答:
You need to artificially add a column that indicates your preferred sorting order, then sort by it, and project it away:

```<code>// Synthetic data - don't copy this
let YourResult = datatable(perfBucket:string, count_:long) [
    "250ms-500ms", 14000,
    "7sec-15sec", 600,
    "1sec-3sec", 9700
];
// This is the actual query
YourResult
| extend sortOrder =
    case(perfBucket == "<250ms", 1,
         perfBucket == "250ms-500ms", 2,
         perfBucket == "500ms-1sec", 3,
         perfBucket == "1sec-3sec", 4,
         perfBucket == "3sec-7sec", 5,
         perfBucket == "7sec-15sec", 6,
         perfBucket == "15sec-30sec", 7,
         perfBucket == "30sec-1min" ,8,
         perfBucket == "1min-2min", 9,
         10)
| order by sortOrder asc
| project-away sortOrder
</code>```

Result:

perfBucket
count_

250ms-500ms
14000

1sec-3sec
9700

7sec-15sec
600

ContentLicense: CC BY-SA 4.0

Body:
You need to artificially add a column that indicates your preferred sorting order, then sort by it, and project it away:

// Synthetic data - don't copy this
let YourResult = datatable(perfBucket:string, count_:long) [
    "250ms-500ms", 14000,
    "7sec-15sec", 600,
    "1sec-3sec", 9700
];
// This is the actual query
YourResult
| extend sortOrder =
    case(perfBucket == "<250ms", 1,
         perfBucket == "250ms-500ms", 2,
         perfBucket == "500ms-1sec", 3,
         perfBucket == "1sec-3sec", 4,
         perfBucket == "3sec-7sec", 5,
         perfBucket == "7sec-15sec", 6,
         perfBucket == "15sec-30sec", 7,
         perfBucket == "30sec-1min" ,8,
         perfBucket == "1min-2min", 9,
         10)
| order by sortOrder asc
| project-away sortOrder

Result:

perfBucket
count_

250ms-500ms
14000

1sec-3sec
9700

7sec-15sec
600


问:
Alternatives ways to getting the properties of the file?
Background:

I have a file monitoring service that watches for changes in the files on the local system using the FileSystemWatcher class and i am handling for events like Created,Deleted,Renamed. When these events are triggered,I would simply want to GET THE PROPERTIES OF THE FILE such as FileName,FileSize,CreationTime,LastAccessTime,LastWriteTime using the FileSystemInfo class.

Problem:

While this service is running, I am unable to uninstall some programs for example (Microsoft Security Essentials). I have a feeling that these service is HANGING ON TO THE RESOURCES of the files marked for deletion because I can only uninstall those programs if only this service is running.

My Question is how can I GET THE PROPERTIES OF THE FILE (as specified above) in an ALTERNATIVE & efficient way without hanging on to the resources of the file ?

Here is my code using the FileSystemInfo

```<code>public void OnCreate/OnRenamed(object source, FileSystemEventArgs e)

{ FileInfo file = new FileInfo(e.FullPath);

String output = "<Event><TimeStamp>" + currentTime + "</TimeStamp>";
            output += "<Name>" + action + "</Name>";
            output += "<Properties><FileName>" + file.Name + "</FileName>";
            output += "<FullPath>" + file.FullName + "</FullPath>";
            output += "<FileSize>" + file.Length + "</FileSize>";
            output += "<CreationTime>" + String.Format("{0:yyyyMMdd-HHmmss.fff}", file.CreationTime) + "</CreationTime>";
            output += "<LastAccess>" + String.Format("{0:yyyyMMdd-HHmmss.fff}", file.LastAccessTime) + "</LastAccess>";
            output += "<LastWriteTime>" + String.Format("{0:yyyyMMdd-HHmmss.fff}", file.LastWriteTime = DateTime.Now) + "</LastWriteTime></Properties></Event>";

}
</code>```

Sincerely,
Derek

答: What you could do is every interval check for LastAccessTime and LastWriteTime and do some quick math based on the interval and you can determine if the file was last accessed or modified within the interval time.  If it was, do what you have to do.  Just an idea...</p>

ContentLicense: CC BY-SA 3.0

Body:
Background:

I have a file monitoring service that watches for changes in the files on the local system using the FileSystemWatcher class and i am handling for events like Created,Deleted,Renamed. When these events are triggered,I would simply want to GET THE PROPERTIES OF THE FILE such as FileName,FileSize,CreationTime,LastAccessTime,LastWriteTime using the FileSystemInfo class.

Problem:

While this service is running, I am unable to uninstall some programs for example (Microsoft Security Essentials). I have a feeling that these service is HANGING ON TO THE RESOURCES of the files marked for deletion because I can only uninstall those programs if only this service is running.

My Question is how can I GET THE PROPERTIES OF THE FILE (as specified above) in an ALTERNATIVE & efficient way without hanging on to the resources of the file ?

Here is my code using the FileSystemInfo

public void OnCreate/OnRenamed(object source, FileSystemEventArgs e)

{ FileInfo file = new FileInfo(e.FullPath);

String output = "<Event><TimeStamp>" + currentTime + "</TimeStamp>";
            output += "<Name>" + action + "</Name>";
            output += "<Properties><FileName>" + file.Name + "</FileName>";
            output += "<FullPath>" + file.FullName + "</FullPath>";
            output += "<FileSize>" + file.Length + "</FileSize>";
            output += "<CreationTime>" + String.Format("{0:yyyyMMdd-HHmmss.fff}", file.CreationTime) + "</CreationTime>";
            output += "<LastAccess>" + String.Format("{0:yyyyMMdd-HHmmss.fff}", file.LastAccessTime) + "</LastAccess>";
            output += "<LastWriteTime>" + String.Format("{0:yyyyMMdd-HHmmss.fff}", file.LastWriteTime = DateTime.Now) + "</LastWriteTime></Properties></Event>";

}

Sincerely,
Derek


问:
Atleast two different condition in where clause in Oracle
I need sql for CC order for which conditions are as below:

order is G If at least one order line has HAZ = Y

order is CC If at least one order line has UD = Y and atleast one of the line has HAZ = Y

for order G sql is as below:

```<code>SELECT DISTINCT oh.order_id
FROM order oh, order ol
WHERE oh.order_id = ol.order_id
AND ol.sku_id IN (SELECT sku_id FROM dcsdba.sku WHERE haz = 'Y' AND client_id = 'C')
AND oh.client_id = 'C';
</code>```

答:
If I understand your conditions correctly, the query should be something like:

```<code>SELECT DISTINCT order_id
  FROM orders ords
 WHERE client_id = 'C'
   AND EXISTS (SELECT 1
                 FROM dcsdba.sku
                WHERE haz       = 'Y'
                  AND client_id = 'C'
                  AND sku_id    = ords.sku_id)
   AND EXISTS (SELECT 1
                 FROM dcsdba.sku
                WHERE ud        = 'Y'
                  AND client_id = 'C'
                  AND sku_id    = ords.sku_id);
</code>```

what you should be utilizing is the EXISTS clause.

Body:
I need sql for CC order for which conditions are as below:

order is G If at least one order line has HAZ = Y

order is CC If at least one order line has UD = Y and atleast one of the line has HAZ = Y

for order G sql is as below:

SELECT DISTINCT oh.order_id
FROM order oh, order ol
WHERE oh.order_id = ol.order_id
AND ol.sku_id IN (SELECT sku_id FROM dcsdba.sku WHERE haz = 'Y' AND client_id = 'C')
AND oh.client_id = 'C';

Body:
If I understand your conditions correctly, the query should be something like:

SELECT DISTINCT order_id
  FROM orders ords
 WHERE client_id = 'C'
   AND EXISTS (SELECT 1
                 FROM dcsdba.sku
                WHERE haz       = 'Y'
                  AND client_id = 'C'
                  AND sku_id    = ords.sku_id)
   AND EXISTS (SELECT 1
                 FROM dcsdba.sku
                WHERE ud        = 'Y'
                  AND client_id = 'C'
                  AND sku_id    = ords.sku_id);

what you should be utilizing is the EXISTS clause.


问:
How can we extend chart legend in Foundry-Slate
In slate, chart widget have label option that display legend (color dot + label name) at some place of the chart (top, left, bottom, ...).

I notice 2 limitations with this legend on bar chart and I would like to improve them on my Slate apps.

1 issue: label are ordered in the order series appears on the bar chart (from left to right).

2 issue: when segmented and not-segmented data are stacked on the bar chart, label of not-segmented data have wrong color (even if we set series color parameter, and if we don't color attribution is random and change from one loading to the next).

For that reason I decided to produce my on labels in an HTML widget. I get a nice result just with  a function that sort label and return a
${labelName}<\div> for each label. But I loose the interactivity (this is a convenient function of labels).

Is there a way to transfer this interactivity to my "custom label" and make click on this selecting all relevant bars on my bar chart?

I'm thinking to use slClickEvent and slClickEventValue props on the DIVs to push data relative to the clicked Label in a variable and to make the bar chart "selectedValue" property dependant of this variable.

Is it the best ways ?

Will the bar be highlighted in accorance with chart "selectedValue"?

答:
You're on the correct track here - I often build custom chart legends in an HTML widget to have more control over the appearance and interaction compared to the native legend. If you search on your Foundry instance, you'll even find a folder of Slate apps that are examples of different HTML widget patterns, including one called HTML - Legend that shows some examples with custom CSS and Blueprint styles.

For the interactivity, I'd probably go with using custom HTML selection, rather than custom HTML click events, because with the custom selection, Slate will automatically add a selected class to whatever element you've added the selection to, which will make it easy to update the styling to reflect the selection.

Nothing would stop you from doing this with custom clickEvents instead, but you'd then need to also do some more work to reflect the selection status in the legend or else go without that extra affordance.

If you search your Foundry instance for Line Chart Series Selection with Custom Legend you'll find an example that shows exactly this. In that specific example, the Line "selection" is indicated on the chart by changing the line styling; with a Bar chart, you'd actually want to template (with Handlebars) the selection status of the chart in the </> panel. Then, when the user makes a selection using the legend, the chart will reflect that selection as if they'd chosen by clicking on the bars themselves.


问:
How to proxy to another URL without redirect
Is it possible to use nginx to work like this:

When going to x.com/blog  -> display the content of blog.x.com (with all the query parameters, etc) without changing the browser URL (without browser redirecting)

I tried

```<code>location /blog {
 proxy_pass https://blog.x.com
}
</code>```

but that didn't work

答:
This nginx config works for me.</p>
```<code>server {
    listen       80;
    listen       [::]:80;
    server_name  x.com;

    location /blog {
        proxy_pass https://blog.x.com;
        proxy_set_header Host blog.x.com;
    }
}

</code>```

Body:
Is it possible to use nginx to work like this:

When going to x.com/blog  -> display the content of blog.x.com (with all the query parameters, etc) without changing the browser URL (without browser redirecting)

I tried

location /blog {
 proxy_pass https://blog.x.com
}

but that didn't work

Body:
This nginx config works for me.

server {
    listen       80;
    listen       [::]:80;
    server_name  x.com;

    location /blog {
        proxy_pass https://blog.x.com;
        proxy_set_header Host blog.x.com;
    }
}


问:
Trying to subtract a day or add a day to a pine script timestamp
In pine script I have an input.time(). I am trying to change the background color one day before, the day of and several days after to different colors. I am doing this to highlight days where an event happened in a list of tickers.
I have tried  to use:

```<code>starttime   = input.time(timestamp("01 Nov 2021 00:00"), "Start Time")
prerange    = time <= starttime and time_close[2] >= starttime
bgcolor(prerange ? #0000FF : na)
</code>```

I have gotten it to work between two timestamps but found no way to simply add or subtract a day from a timestamp.

答:
Timestamps are in unix time which is in milliseconds (since Jan 1st 1970).

One day in milliseconds is 86400000ms. We can use this value to add/subtract from the timestamp.

```<code>starttime   = input.time(timestamp("01 Nov 2021 00:00"), "Start Time")
event_days  = input.int(2)
post_days   = input.int(5)

pre_ts = starttime - 86400000
post_start_ts = starttime + 86400000 * event_days
post_end_ts = starttime + 86400000 * (event_days + post_days)

pre_range = time >= pre_ts and time < starttime
post_range = time >= post_start_ts and time < post_end_ts

bgcolor(pre_range ? #0000FF : na)
bgcolor(post_range ? #00FF00 : na)
</code>```

Body:
In pine script I have an input.time(). I am trying to change the background color one day before, the day of and several days after to different colors. I am doing this to highlight days where an event happened in a list of tickers.
I have tried  to use:

starttime   = input.time(timestamp("01 Nov 2021 00:00"), "Start Time")
prerange    = time <= starttime and time_close[2] >= starttime
bgcolor(prerange ? #0000FF : na)

I have gotten it to work between two timestamps but found no way to simply add or subtract a day from a timestamp.

Body:
Timestamps are in unix time which is in milliseconds (since Jan 1st 1970).

One day in milliseconds is 86400000ms. We can use this value to add/subtract from the timestamp.

starttime   = input.time(timestamp("01 Nov 2021 00:00"), "Start Time")
event_days  = input.int(2)
post_days   = input.int(5)

pre_ts = starttime - 86400000
post_start_ts = starttime + 86400000 * event_days
post_end_ts = starttime + 86400000 * (event_days + post_days)

pre_range = time >= pre_ts and time < starttime
post_range = time >= post_start_ts and time < post_end_ts

bgcolor(pre_range ? #0000FF : na)
bgcolor(post_range ? #00FF00 : na)


问:
Docker run command like in Visual Studio
When running a Standard ASP.NET Core Web API project created by Visual Studio 2022 with docker option enabled, connecting to the server via browser is possible by using https://localhost:65215/swagger/index.html (which even pops up by itself).

When running the container with specifying the mapping of port 80 and 443 (such as 65214 and 65215), reaching Swagger is not possible on the specified ports. So there must clearly be more to it.

How can one run the docker container from the console, using a docker run command? And how can the port be set or at least identified?

Dockerfile

```<code>FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["WebApiContainerized/WebApiContainerized.csproj", "WebApiContainerized/"]
RUN dotnet restore "WebApiContainerized/WebApiContainerized.csproj"
COPY . .
WORKDIR "/src/WebApiContainerized"
RUN dotnet build "WebApiContainerized.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebApiContainerized.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApiContainerized.dll"]
</code>```

Program.cs

```<code>var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI(); }

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
</code>```

Project creation

答:
By default, Swagger is only available when you run your app in the 'development' environment.

By default, a containerized app runs in production.

To change it, you set the ASPNETCORE_ENVIRONMENT variable to 'Development'. You can either do that on the docker run or you can set it in the Dockerfile.

As for the ports, Microsoft set ASPNETCORE_URLS to http://+:80 in the aspnet images, causing the app to listen on port 80.

Add a line to set ASPNETCORE_ENVIRONMENT to your Dockerfile like this

```<code>FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
ENV ASPNETCORE_ENVIRONMENT Development
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["WebApiContainerized/WebApiContainerized.csproj", "WebApiContainerized/"]
RUN dotnet restore "WebApiContainerized/WebApiContainerized.csproj"
COPY . .
WORKDIR "/src/WebApiContainerized"
RUN dotnet build "WebApiContainerized.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebApiContainerized.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApiContainerized.dll"]
</code>```

Build and run with

```<code>docker build -t myimage .
docker run -d -p 65214:80 myimage
</code>```

You should now be able to reach the Swagger page at http://localhost:65214/swagger

Body:
When running a Standard ASP.NET Core Web API project created by Visual Studio 2022 with docker option enabled, connecting to the server via browser is possible by using https://localhost:65215/swagger/index.html (which even pops up by itself).

When running the container with specifying the mapping of port 80 and 443 (such as 65214 and 65215), reaching Swagger is not possible on the specified ports. So there must clearly be more to it.

How can one run the docker container from the console, using a docker run command? And how can the port be set or at least identified?

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["WebApiContainerized/WebApiContainerized.csproj", "WebApiContainerized/"]
RUN dotnet restore "WebApiContainerized/WebApiContainerized.csproj"
COPY . .
WORKDIR "/src/WebApiContainerized"
RUN dotnet build "WebApiContainerized.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebApiContainerized.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApiContainerized.dll"]

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI(); }

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Project creation

Body:
By default, Swagger is only available when you run your app in the 'development' environment.

By default, a containerized app runs in production.

To change it, you set the ASPNETCORE_ENVIRONMENT variable to 'Development'. You can either do that on the docker run or you can set it in the Dockerfile.

As for the ports, Microsoft set ASPNETCORE_URLS to http://+:80 in the aspnet images, causing the app to listen on port 80.

Add a line to set ASPNETCORE_ENVIRONMENT to your Dockerfile like this

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
ENV ASPNETCORE_ENVIRONMENT Development
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["WebApiContainerized/WebApiContainerized.csproj", "WebApiContainerized/"]
RUN dotnet restore "WebApiContainerized/WebApiContainerized.csproj"
COPY . .
WORKDIR "/src/WebApiContainerized"
RUN dotnet build "WebApiContainerized.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebApiContainerized.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApiContainerized.dll"]

Build and run with

docker build -t myimage .
docker run -d -p 65214:80 myimage

You should now be able to reach the Swagger page at http://localhost:65214/swagger


问:
Flutter - How can I print all my data (fields) from firebase documents?
I would like to show all the fields of a document in firebase, but I'm having different troubles.

My intention is to show the info like a chat. I tried with a ListView.builder inside a StreamBuilder.

This is my Firestore document:

I managed to get the horizontal information using doc.data().toString but what I am trying to do is to get the whole information as a ListTile so when I add new messages they are automatically added to the ListView.builder.

This is my current code:

```<code>import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class ChatScreen extends StatefulWidget {
  const ChatScreen({Key? key}) : super(key: key);

  @override
  State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final textController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.only(left: 20.0),
        child: StreamBuilder(
            stream:
                FirebaseFirestore.instance.collection("messages").snapshots(),
            builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (!snapshot.hasData) {
                return Center(child: CircularProgressIndicator());
              }
              return ListView.builder(
                itemCount: snapshot.data!.docs.length,
                itemBuilder: (context, index) {
                  DocumentSnapshot doc = snapshot.data!.docs[index];
                  return ListTile(
                    title: Text(doc.data().toString()),
                  );
                },
              );
            }),
      ),
    );
  }
}
</code>```

And this is what I get with my current code: DeviceImage

P.S. I can get the data manually if I use this but it's not what I want:

```<code>return ListTile(
                    title: Text(doc['sender']),
                  );
</code>```

答:
Try with this.

```<code>return StreamBuilder<QuerySnapshot>(
      stream: FirebaseFirestore.instance
          .collection("messages")
          .snapshots(),
      builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
        return ListView.builder(
          shrinkWrap: true,
          primary: false,
          itemCount: snapshot.hasData ? snapshot.data.docs.length : 0,
          itemBuilder: (context, index) {
            final data = MessageModel.fromSnapshot(snapshot.data.docs[index]);
            return ListTile(
              title: Text(data.text),
              subtitle: Text(data.sender),
            );
          },
        );
      },
    );
</code>```

MessageModel

```<code>class MessageModel {
  MessageModel({
    this.sender,
    this.text,
  });

  String sender;
  String text;

  String toRawJson() => json.encode(toJson());

  factory MessageModel.fromSnapshot(DocumentSnapshot snapshot) {
    final model =
        MessageModel.fromJson(snapshot.data() as Map<String, dynamic>);
    return model;
  }

  factory MessageModel.fromJson(Map<String, dynamic> json) => MessageModel(
        sender: json["sender"] == null ? null : json["sender"],
        text: json["text"] == null ? null : json["text"],
      );

  Map<String, dynamic> toJson() => {
        "sender": sender == null ? null : sender,
        "text": text == null ? null : text,
      };
}
</code>```

Body:
I would like to show all the fields of a document in firebase, but I'm having different troubles.

My intention is to show the info like a chat. I tried with a ListView.builder inside a StreamBuilder.

This is my Firestore document:

I managed to get the horizontal information using doc.data().toString but what I am trying to do is to get the whole information as a ListTile so when I add new messages they are automatically added to the ListView.builder.

This is my current code:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class ChatScreen extends StatefulWidget {
  const ChatScreen({Key? key}) : super(key: key);

  @override
  State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final textController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.only(left: 20.0),
        child: StreamBuilder(
            stream:
                FirebaseFirestore.instance.collection("messages").snapshots(),
            builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (!snapshot.hasData) {
                return Center(child: CircularProgressIndicator());
              }
              return ListView.builder(
                itemCount: snapshot.data!.docs.length,
                itemBuilder: (context, index) {
                  DocumentSnapshot doc = snapshot.data!.docs[index];
                  return ListTile(
                    title: Text(doc.data().toString()),
                  );
                },
              );
            }),
      ),
    );
  }
}

And this is what I get with my current code: DeviceImage

P.S. I can get the data manually if I use this but it's not what I want:

return ListTile(
                    title: Text(doc['sender']),
                  );

Body:
Try with this.

return StreamBuilder<QuerySnapshot>(
      stream: FirebaseFirestore.instance
          .collection("messages")
          .snapshots(),
      builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
        return ListView.builder(
          shrinkWrap: true,
          primary: false,
          itemCount: snapshot.hasData ? snapshot.data.docs.length : 0,
          itemBuilder: (context, index) {
            final data = MessageModel.fromSnapshot(snapshot.data.docs[index]);
            return ListTile(
              title: Text(data.text),
              subtitle: Text(data.sender),
            );
          },
        );
      },
    );

MessageModel

class MessageModel {
  MessageModel({
    this.sender,
    this.text,
  });

  String sender;
  String text;

  String toRawJson() => json.encode(toJson());

  factory MessageModel.fromSnapshot(DocumentSnapshot snapshot) {
    final model =
        MessageModel.fromJson(snapshot.data() as Map<String, dynamic>);
    return model;
  }

  factory MessageModel.fromJson(Map<String, dynamic> json) => MessageModel(
        sender: json["sender"] == null ? null : json["sender"],
        text: json["text"] == null ? null : json["text"],
      );

  Map<String, dynamic> toJson() => {
        "sender": sender == null ? null : sender,
        "text": text == null ? null : text,
      };
}


问:
Concatenating CSS with cache control
Ok, here's a tough one:

I have these website with several CSS files that uses cache busting and it worked fine. i was getting 403 Not Modified with every call.

But now Im using this rule in my htaccess to concatenate all my files

```<code>
<FilesMatch "\.combined\.css$">
  Options +Includes
  AddOutputFilterByType INCLUDES text/css
  SetOutputFilter INCLUDES
</FilesMatch>
</code>```

Inside script.combined.css you can find this:

```<code>
<!--#include file="file1.css" -->
<!--#include file="file2.css" -->
</code>```

The problem comes that even though my file "script.combined.css" uses cache busting. it's always returning "200 Ok". These are the headers of script.combined.css:

```<code>
Request

URL:http://XXX/css/script.combined.css
Request Method:GET
Status Code:200 OK

Request Headers

Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:typo3-login-cookiecheck=true; PHPSESSID=2evc53ngjjobateti38gpahtt7; tx_phpmyadmin=quf4sgevagubd1snd9eoq4g4d0; be_typo_user=0f4c7e291b6d7673310d6f15da687910; Typo3InstallTool=62erpih8fmqbbl3pe75pcenuu0; fe_typo_user=a7e5de71521603161fa598ed523b024b
Host:XXX
Referer:http://XXX/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/11.04 Chromium/12.0.742.112 Chrome/12.0.742.112 Safari/534.30

Response Headers

Accept-Ranges:bytes
Cache-Control:max-age=31536000, public
Connection:Keep-Alive
Content-Type:text/css
Date:Wed, 17 Aug 2011 13:56:42 GMT
Expires:Thu, 16 Aug 2012 13:56:42 GMT
Keep-Alive:timeout=5, max=99
Server:HTTPD
Transfer-Encoding:chunked
</code>```

...while these are the headers for another simple css file:

```<code>
Request URL:http://XXX/css/style.css
Request Method:GET
Status Code:304 Not Modified

Request Headers

Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:typo3-login-cookiecheck=true; PHPSESSID=2evc53ngjjobateti38gpahtt7; tx_phpmyadmin=quf4sgevagubd1snd9eoq4g4d0; be_typo_user=0f4c7e291b6d7673310d6f15da687910; Typo3InstallTool=62erpih8fmqbbl3pe75pcenuu0; fe_typo_user=a7e5de71521603161fa598ed523b024b
Host:XXX
If-Modified-Since:Wed, 17 Aug 2011 11:45:17 GMT
Referer:http://XXX/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/11.04 Chromium/12.0.742.112 Chrome/12.0.742.112 Safari/534.30

Response Headers

Cache-Control:max-age=31536000, public
Connection:Keep-Alive
Date:Wed, 17 Aug 2011 13:56:42 GMT
Expires:Thu, 16 Aug 2012 13:56:42 GMT
Keep-Alive:timeout=5, max=97
Server:HTTPD
</code>```

I used an extension to measure Page Speed from google and I got this message:

Specify a cache validator

The following resources are missing a cache validator. Resources that
  do not specify a cache validator cannot be refreshed efficiently.
  Specify a Last-Modified or ETag header to enable cache validation for
  the following resources:

http://XXX/css/script.combined.css?1313583214

What should I do??

答:
According to Apache's documentation for server side includes:

In its default configuration, Apache does not send the last modified date or content length HTTP headers on SSI pages, because these values are difficult to calculate for dynamic content.

http://httpd.apache.org/docs/1.3/howto/ssi.html

So a direct request in your browser to styles.combined.css will never return a 304 Not Modified status.

But if you're setting expires headers, the browser simply pulls the asset from the local cache. The request to check the last-modified date is unnecessary and doesn't get sent.

Title: Concatenating CSS with cache control

Body:
Ok, here's a tough one:

I have these website with several CSS files that uses cache busting and it worked fine. i was getting 403 Not Modified with every call.

But now Im using this rule in my htaccess to concatenate all my files

<FilesMatch "\.combined\.css$">
  Options +Includes
  AddOutputFilterByType INCLUDES text/css
  SetOutputFilter INCLUDES
</FilesMatch>

Inside script.combined.css you can find this:

The problem comes that even though my file "script.combined.css" uses cache busting. it's always returning "200 Ok". These are the headers of script.combined.css:

Request

URL:http://XXX/css/script.combined.css
Request Method:GET
Status Code:200 OK

Request Headers

Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:typo3-login-cookiecheck=true; PHPSESSID=2evc53ngjjobateti38gpahtt7; tx_phpmyadmin=quf4sgevagubd1snd9eoq4g4d0; be_typo_user=0f4c7e291b6d7673310d6f15da687910; Typo3InstallTool=62erpih8fmqbbl3pe75pcenuu0; fe_typo_user=a7e5de71521603161fa598ed523b024b
Host:XXX
Referer:http://XXX/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/11.04 Chromium/12.0.742.112 Chrome/12.0.742.112 Safari/534.30

Response Headers

Accept-Ranges:bytes
Cache-Control:max-age=31536000, public
Connection:Keep-Alive
Content-Type:text/css
Date:Wed, 17 Aug 2011 13:56:42 GMT
Expires:Thu, 16 Aug 2012 13:56:42 GMT
Keep-Alive:timeout=5, max=99
Server:HTTPD
Transfer-Encoding:chunked

...while these are the headers for another simple css file:

Request URL:http://XXX/css/style.css
Request Method:GET
Status Code:304 Not Modified

Request Headers

Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:typo3-login-cookiecheck=true; PHPSESSID=2evc53ngjjobateti38gpahtt7; tx_phpmyadmin=quf4sgevagubd1snd9eoq4g4d0; be_typo_user=0f4c7e291b6d7673310d6f15da687910; Typo3InstallTool=62erpih8fmqbbl3pe75pcenuu0; fe_typo_user=a7e5de71521603161fa598ed523b024b
Host:XXX
If-Modified-Since:Wed, 17 Aug 2011 11:45:17 GMT
Referer:http://XXX/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/11.04 Chromium/12.0.742.112 Chrome/12.0.742.112 Safari/534.30

Response Headers

Cache-Control:max-age=31536000, public
Connection:Keep-Alive
Date:Wed, 17 Aug 2011 13:56:42 GMT
Expires:Thu, 16 Aug 2012 13:56:42 GMT
Keep-Alive:timeout=5, max=97
Server:HTTPD

I used an extension to measure Page Speed from google and I got this message:

Specify a cache validator

The following resources are missing a cache validator. Resources that
  do not specify a cache validator cannot be refreshed efficiently.
  Specify a Last-Modified or ETag header to enable cache validation for
  the following resources:

http://XXX/css/script.combined.css?1313583214

What should I do??


问:
Where can I get groovy-all-4.0.0.jar?
Where can I get/download groovy-all-4.0.0.jar containing all the important Groovy 4.0 modules/classes in one file?

Till now I've found only a pom file, but I cannot use Maven.

https://repo1.maven.org/maven2/org/apache/groovy/groovy-all/4.0.0/groovy-all-4.0.0.pom

答:
Go to Maven Central's search page:

https://search.maven.org/

Type groovy-all. Select the latest version. Click on "Browse" on the top-right.

You'll get to this page:

https://repo1.maven.org/maven2/org/apache/groovy/groovy-all/4.0.0/

From here, you can copy the links to all jars and download that by clicking on it or using wget, curl or what have you.

EDIT: the groovy-all module on Maven Central is now a POM module. This means it's just grouping all the Groovy jars (most of them, actually).
As announced on the Groovy 2.5 release notes, the groovy-all jar is no longer published. That is, you're expected to use a tool like Maven, Gradle or Ivy to download the jars from the groovy-all Maven artifact (as the transitive dependencies must be downloaded as well).

I suggest you use mvn dependency:get to download all the dependencies (unfortunately, it will only install the artifacts in the local maven repository instead of on a single directory like you probably want), or use Gradle like this:

```<code>repositories {
  mavenCentral()
}
configurations {
  groovy
}
dependencies {
  groovy 'org.apache.groovy:groovy-all:4.0.0'
}
task downloadGroovy(type: Copy) {
  from configurations.groovy
  into file('groovy-jars')
}
</code>```

Put this into a build.gradle file, then from the same directory, run gradle downloadGroovy. It will download all the jars into the groovy-jars directory.

Notice, however, that this is almost certainly not what you want. You most likely should pick and choose which groovy jars you actually need and only download those.

Here's the list of Jars I get when I use Gradle to download the jars:

```<code>ant-1.10.12.jar                     groovy-datetime-4.0.0.jar           groovy-templates-4.0.0.jar          jline-2.14.6.jar
ant-antlr-1.10.12.jar               groovy-docgenerator-4.0.0.jar       groovy-test-4.0.0.jar               junit-4.13.2.jar
ant-junit-1.10.12.jar               groovy-groovydoc-4.0.0.jar          groovy-test-junit5-4.0.0.jar        junit-jupiter-api-5.8.2.jar
ant-launcher-1.10.12.jar            groovy-groovysh-4.0.0.jar           groovy-xml-4.0.0.jar                junit-jupiter-engine-5.8.2.jar
asm-9.2.jar                         groovy-jmx-4.0.0.jar                groovy-yaml-4.0.0.jar               junit-platform-commons-1.8.2.jar
asm-analysis-9.2.jar                groovy-json-4.0.0.jar               hamcrest-core-1.3.jar               junit-platform-engine-1.8.2.jar
asm-tree-9.2.jar                    groovy-jsr223-4.0.0.jar             ivy-2.5.0.jar                       junit-platform-launcher-1.8.2.jar
asm-util-9.2.jar                    groovy-macro-4.0.0.jar              jackson-annotations-2.13.1.jar      opentest4j-1.2.0.jar
groovy-4.0.0.jar                    groovy-nio-4.0.0.jar                jackson-core-2.13.1.jar             org.abego.treelayout.core-1.0.3.jar
groovy-ant-4.0.0.jar                groovy-servlet-4.0.0.jar            jackson-databind-2.13.1.jar         picocli-4.6.2.jar
groovy-cli-picocli-4.0.0.jar        groovy-sql-4.0.0.jar                jackson-dataformat-yaml-2.13.1.jar  qdox-1.12.1.jar
groovy-console-4.0.0.jar            groovy-swing-4.0.0.jar              javaparser-core-3.24.0.jar          snakeyaml-1.28.jar
</code>```

This includes everything Groovy needs to run as a CLI, REPL, grab dependencies with Ivy, compile code at runtime etc. Do you need all that? If you do, then go ahead and use groovy-all, otherwise, it's advisable to look for the jars you actually are going to use.

Title: Where can I get groovy-all-4.0.0.jar?

Body:
Go to Maven Central's search page:

https://search.maven.org/

Type groovy-all. Select the latest version. Click on "Browse" on the top-right.

You'll get to this page:

https://repo1.maven.org/maven2/org/apache/groovy/groovy-all/4.0.0/

From here, you can copy the links to all jars and download that by clicking on it or using wget, curl or what have you.

EDIT: the groovy-all module on Maven Central is now a POM module. This means it's just grouping all the Groovy jars (most of them, actually).
As announced on the Groovy 2.5 release notes, the groovy-all jar is no longer published. That is, you're expected to use a tool like Maven, Gradle or Ivy to download the jars from the groovy-all Maven artifact (as the transitive dependencies must be downloaded as well).

I suggest you use mvn dependency:get to download all the dependencies (unfortunately, it will only install the artifacts in the local maven repository instead of on a single directory like you probably want), or use Gradle like this:

repositories {
  mavenCentral()
}
configurations {
  groovy
}
dependencies {
  groovy 'org.apache.groovy:groovy-all:4.0.0'
}
task downloadGroovy(type: Copy) {
  from configurations.groovy
  into file('groovy-jars')
}

Put this into a build.gradle file, then from the same directory, run gradle downloadGroovy. It will download all the jars into the groovy-jars directory.

Notice, however, that this is almost certainly not what you want. You most likely should pick and choose which groovy jars you actually need and only download those.

Here's the list of Jars I get when I use Gradle to download the jars:

ant-1.10.12.jar                     groovy-datetime-4.0.0.jar           groovy-templates-4.0.0.jar          jline-2.14.6.jar
ant-antlr-1.10.12.jar               groovy-docgenerator-4.0.0.jar       groovy-test-4.0.0.jar               junit-4.13.2.jar
ant-junit-1.10.12.jar               groovy-groovydoc-4.0.0.jar          groovy-test-junit5-4.0.0.jar        junit-jupiter-api-5.8.2.jar
ant-launcher-1.10.12.jar            groovy-groovysh-4.0.0.jar           groovy-xml-4.0.0.jar                junit-jupiter-engine-5.8.2.jar
asm-9.2.jar                         groovy-jmx-4.0.0.jar                groovy-yaml-4.0.0.jar               junit-platform-commons-1.8.2.jar
asm-analysis-9.2.jar                groovy-json-4.0.0.jar               hamcrest-core-1.3.jar               junit-platform-engine-1.8.2.jar
asm-tree-9.2.jar                    groovy-jsr223-4.0.0.jar             ivy-2.5.0.jar                       junit-platform-launcher-1.8.2.jar
asm-util-9.2.jar                    groovy-macro-4.0.0.jar              jackson-annotations-2.13.1.jar      opentest4j-1.2.0.jar
groovy-4.0.0.jar                    groovy-nio-4.0.0.jar                jackson-core-2.13.1.jar             org.abego.treelayout.core-1.0.3.jar
groovy-ant-4.0.0.jar                groovy-servlet-4.0.0.jar            jackson-databind-2.13.1.jar         picocli-4.6.2.jar
groovy-cli-picocli-4.0.0.jar        groovy-sql-4.0.0.jar                jackson-dataformat-yaml-2.13.1.jar  qdox-1.12.1.jar
groovy-console-4.0.0.jar            groovy-swing-4.0.0.jar              javaparser-core-3.24.0.jar          snakeyaml-1.28.jar

This includes everything Groovy needs to run as a CLI, REPL, grab dependencies with Ivy, compile code at runtime etc. Do you need all that? If you do, then go ahead and use groovy-all, otherwise, it's advisable to look for the jars you actually are going to use.


问:
Why to use @Autowired to run Kafka Streams topology in a Spring Boot Application?
I am trying to run Kafka Streams Topology inside a spring boot application.

In the example on confluent website they did the following:

```<code>@Component
class Processor {
    @Autowired
    public void process(final StreamsBuilder builder) {
        // the logic to run the topology which is a blocking call
    }
}
</code>```

I think the @Autowired annotation means that the method process will be invoked by the Spring framework.

My question is: Given that the call to the method process is blocking call
is this the best practice to run the topology inside a spring boot application?
Why not run it in a separate thread?

答:
@Autowired instructs Spring to inject an existing StreamsBuilder bean as a parameter to the process(...) function. This is done while bootstrapping the application context, so it will not block the running topology itself which is started as a seperate thread via some kind of new KafkaStreams(builder.build(), props);

Therefore this is absolutely okay to do.

Body:
I am trying to run Kafka Streams Topology inside a spring boot application.

In the example on confluent website they did the following:

@Component
class Processor {
    @Autowired
    public void process(final StreamsBuilder builder) {
        // the logic to run the topology which is a blocking call
    }
}

I think the @Autowired annotation means that the method process will be invoked by the Spring framework.

My question is: Given that the call to the method process is blocking call
is this the best practice to run the topology inside a spring boot application?
Why not run it in a separate thread?


问:
Telegram bot doorbell - Raspberry Pi
I'm new to python and raspberry, I would like to make a smart doorbell controlled by a bot on telegram. The doorbell in question has a pir sensor that sends a video over telegram every time its triggered. I would like to have the messages I send to the bot read through the speakers.
But I have a problem with the while true loop of the sensor and the handle (msg) function of telepot, I need to take the chat_id variable out of the handle function to use it in the other functions but I can't. I am attaching the complete code:

```<code>import telepot
from picamera import PiCamera
import RPi.GPIO as GPIO
import time
from time import sleep
import datetime
from telepot.loop import MessageLoop
from subprocess import call
import sys
import random
import pyttsx3

# setup sensori
PIR = 4
camera = PiCamera()
camera.resolution = (680, 480)
camera.framerate = 25
camera.rotation = 180

# setup pin
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR, GPIO.IN)

# variabili movimento
motion = 0
motionNew = 0

# telegram bot
def handle(msg):
    global telegramText
    global chat_id

    chat_id = msg['chat']['id']
    telegramText = msg['text']

    print('Messaggio ricevuto! ' + str(chat_id) + telegramText)

    # start engine per leggere i messaggi
    engine = pyttsx3.init()
    rate = engine.getProperty('rate')  # variabile per cambiare velocita
    engine.setProperty('rate', rate-50)  # velocita voce
    voice_id = 'italian'
    engine.setProperty('voice', voice_id)
    engine.say(telegramText)
    engine.runAndWait()

    if telegramText == '/start':
        bot.sendMessage(chat_id, 'Sicurezza del perimetro attiva, sei protetto!')

# connessione bot telegram
bot = telepot.Bot('####')
bot.message_loop(handle)

# definizione funzione principale movimento
def main():
    global chat_id
    global motion
    global motionNew

    if GPIO.input(PIR) == 1:
        print("Movimento rilevato!")
        motion = 1
        if motionNew != motion:
            motionNew = motion
            sendNotification()

    elif GPIO.input(PIR) == 0:
        motion = 0
        if motionNew != motion:
            motionNew = motion

def sendNotification():

    global chat_id

    bot.sendMessage(chat_id, 'ATTENZIONE! Qualcuno è alla porta!')
    filename = "./video_" + (time.strftime("%y%b%d_%H%M%S"))
    camera.start_recording(filename + ".h264")
    sleep(10)
    camera.stop_recording()
    command = "MP4Box -add " + filename + '.h264' + " " + filename + '.mp4'
    print(command)
    call([command], shell=True)
    bot.sendVideo(chat_id, video=open(filename + '.mp4', 'rb'))
    print('Attendo 20 secondi')
    time.sleep(20)

# definizione interrupt
def end_security():
    print('End')

# check continuo sensore pir
try:
    while True:
        main()

except KeyboardInterrupt:
    end_security()
</code>```

I get an error in this line:

```<code>bot.sendMessage(chat_id, 'ATTENZIONE! Qualcuno è alla porta!')
</code>```

error:

```<code>NameError: name 'chat_id' is not defined
</code>```

How can I manage it? Thank you

答:
I think the problem is that when you call sendNotification() before handle() has been called then chat_id has not been set by anything so is undefined.

If you change your main loop code to the following, then you shouldn't get the error, since chat_id will be defined to a value at the beginning of the program.

```<code>    try:
    chat_id=999999999
    while True:
        main()
</code>```

However, I'm not sure what you want chat_id to be set to when you call sendNotification() from the main() function since you don't have a message to take it from? Do you really need chat_id to be a global. It may be better to pass the chat id into sendNotification() as a parameter.

Title: Telegram bot doorbell - Raspberry Pi

Body:
I'm new to python and raspberry, I would like to make a smart doorbell controlled by a bot on telegram. The doorbell in question has a pir sensor that sends a video over telegram every time its triggered. I would like to have the messages I send to the bot read through the speakers.
But I have a problem with the while true loop of the sensor and the handle (msg) function of telepot, I need to take the chat_id variable out of the handle function to use it in the other functions but I can't. I am attaching the complete code:

import telepot
from picamera import PiCamera
import RPi.GPIO as GPIO
import time
from time import sleep
import datetime
from telepot.loop import MessageLoop
from subprocess import call
import sys
import random
import pyttsx3

# setup sensori
PIR = 4
camera = PiCamera()
camera.resolution = (680, 480)
camera.framerate = 25
camera.rotation = 180

# setup pin
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR, GPIO.IN)

# variabili movimento
motion = 0
motionNew = 0

# telegram bot
def handle(msg):
    global telegramText
    global chat_id

    chat_id = msg['chat']['id']
    telegramText = msg['text']

    print('Messaggio ricevuto! ' + str(chat_id) + telegramText)

    # start engine per leggere i messaggi
    engine = pyttsx3.init()
    rate = engine.getProperty('rate')  # variabile per cambiare velocita
    engine.setProperty('rate', rate-50)  # velocita voce
    voice_id = 'italian'
    engine.setProperty('voice', voice_id)
    engine.say(telegramText)
    engine.runAndWait()

    if telegramText == '/start':
        bot.sendMessage(chat_id, 'Sicurezza del perimetro attiva, sei protetto!')

# connessione bot telegram
bot = telepot.Bot('####')
bot.message_loop(handle)

# definizione funzione principale movimento
def main():
    global chat_id
    global motion
    global motionNew

    if GPIO.input(PIR) == 1:
        print("Movimento rilevato!")
        motion = 1
        if motionNew != motion:
            motionNew = motion
            sendNotification()

    elif GPIO.input(PIR) == 0:
        motion = 0
        if motionNew != motion:
            motionNew = motion

def sendNotification():

    global chat_id

    bot.sendMessage(chat_id, 'ATTENZIONE! Qualcuno è alla porta!')
    filename = "./video_" + (time.strftime("%y%b%d_%H%M%S"))
    camera.start_recording(filename + ".h264")
    sleep(10)
    camera.stop_recording()
    command = "MP4Box -add " + filename + '.h264' + " " + filename + '.mp4'
    print(command)
    call([command], shell=True)
    bot.sendVideo(chat_id, video=open(filename + '.mp4', 'rb'))
    print('Attendo 20 secondi')
    time.sleep(20)

# definizione interrupt
def end_security():
    print('End')

# check continuo sensore pir
try:
    while True:
        main()

except KeyboardInterrupt:
    end_security()

I get an error in this line:

bot.sendMessage(chat_id, 'ATTENZIONE! Qualcuno è alla porta!')

error:

NameError: name 'chat_id' is not defined

How can I manage it? Thank you

Body:
I think the problem is that when you call sendNotification() before handle() has been called then chat_id has not been set by anything so is undefined.

If you change your main loop code to the following, then you shouldn't get the error, since chat_id will be defined to a value at the beginning of the program.

    try:
    chat_id=999999999
    while True:
        main()

However, I'm not sure what you want chat_id to be set to when you call sendNotification() from the main() function since you don't have a message to take it from? Do you really need chat_id to be a global. It may be better to pass the chat id into sendNotification() as a parameter.


问:
Rubinius does not recognize methods in the File class
I have a project that has alot of file manipulation.  I am trying out Rubinius because I need to be able to compile the code.  When I try to run code that includes

```<code>if Dir.exist?(file_path)
</code>```

I get this error:

```<code>NoMethodError: undefined method `exist?' on Dir (Class)
</code>```

Is there something I need to include to get this recognized?  Btw, I have also tried Dir.exists? since it is an alias, and that didn't work either.  Is the issue that this method didn't exist in 1.8.7?  I can't seem to find a list of

答: The issue was that Rubinius is using 1.8.7 and this method didn't exist then.</p>

Body:
I have a project that has alot of file manipulation.  I am trying out Rubinius because I need to be able to compile the code.  When I try to run code that includes

if Dir.exist?(file_path)

I get this error:

NoMethodError: undefined method `exist?' on Dir (Class)

Is there something I need to include to get this recognized?  Btw, I have also tried Dir.exists? since it is an alias, and that didn't work either.  Is the issue that this method didn't exist in 1.8.7?  I can't seem to find a list of


问:
No communication between electron app and user AddData on production
I created an electron app that has user configuration/settings (changing of theme, tracking and persisting window's current size and position). I saved the json files that contained all of these in user AppData (app.getPath('userData')) working well on development but after being packaged with electron-builder, the app no longer communicates the AppData. Tried to change the theme but the new colors could not be written in AppData, size and position not changing. Frustrated ...

Please what next should I do if I must use the AppData

```<code>const { app, BrowserWindow, ipcMain } = require("electron");
let isDev = require('electron-is-dev');
const path = require('path');
const fs = require('fs');
const { setColors } = require('./ipc');

const userDir = app.getPath('userData');

let isConfigDir = fs.existsSync(path.join(userDir, 'config'));
let isSizeDir = fs.existsSync(path.join(userDir, 'config/size.json'))
let isPosDir = fs.existsSync(path.join(userDir, 'config/pos.json'));
let isColorDir = fs.existsSync(path.join(userDir, 'config/colors.json'));

//create config dir if not already exists
if(!isConfigDir){
    fs.mkdirSync(path.join(userDir, '/config'))
}

//check and create config files if not already exist
let pos;
if(!isPosDir){
    let pos_ = {"x":636,"y":0};
    fs.writeFileSync(path.join(userDir, 'config/pos.json'), JSON.stringify(pos_));
    pos = pos_
}else{
    pos = JSON.parse(fs.readFileSync(path.join(userDir, 'config/pos.json'), "utf8"))
}

let size
if(!isSizeDir){
    let size_ = {"width":701,"height":768}
    fs.writeFileSync(path.join(userDir, 'config/size.json'), JSON.stringify(size_));
    size = size_;
}else{
    size = JSON.parse(fs.readFileSync(path.join(userDir, 'config/size.json'), "utf8"))
}

ipcMain.handle("getColors", (event, args)=>{
    let colors;
    if(!isColorDir){
        let colors_ = {"bg":"gold","text":"#000"}
        fs.writeFileSync(path.join(userDir, 'config/colors.json'), JSON.stringify(colors_));
        colors = colors_
        return colors;
    }else{
        colors = JSON.parse(fs.readFileSync(path.join(userDir, 'config/colors.json'), "utf8"));
        return colors;
    }
})

let win;
function createWin(){
    win = new BrowserWindow({
        width:size.width,
        height: size.height,
        x: pos.x,
        y: pos.y,
        title: 'BMS',
        webPreferences:{
            preload: path.join(__dirname, "preload.js")
        }
    });
    isDev ? win.loadURL('http://localhost:3000') : win.loadFile('views/build/index.html')

    win.on("closed", ()=>win = null);

    // set window size in file size.json when the system resized
    win.on('resized', ()=>{
        let size = {
            width: win.getBounds().width,
            height: win.getBounds().height,
        }
        fs.writeFileSync(path.join(userDir, 'config/size.json'), JSON.stringify(size))
    })

    // set window position in file size.json when the window moves
    win.on('move', ()=>{
        let pos = {
            x: win.getBounds().x,
            y: win.getBounds().y
        }
        fs.writeFileSync(path.join(userDir, 'config/pos.json'), JSON.stringify(pos))
    })
}

app.on("ready", ()=>{
    //create window
    createWin();

    setColors(userDir)

})

app.on("window-all-closed", ()=>{
    if(process.platform !== 'darwin'){
        app.quit()
    }
})
app.on('active', ()=>{
    if(win===null){
        createWin()
    }
})
</code>```

答:
Looking at your code, I suspect that your /config folder does not exists when running your application. So, all your variables isSizeDir, isPosDir, etc. are false and stays false even after creating the folder on line 17.

I would move the /config folder creation after line 11.

Body:
I created an electron app that has user configuration/settings (changing of theme, tracking and persisting window's current size and position). I saved the json files that contained all of these in user AppData (app.getPath('userData')) working well on development but after being packaged with electron-builder, the app no longer communicates the AppData. Tried to change the theme but the new colors could not be written in AppData, size and position not changing. Frustrated ...

Please what next should I do if I must use the AppData

const { app, BrowserWindow, ipcMain } = require("electron");
let isDev = require('electron-is-dev');
const path = require('path');
const fs = require('fs');
const { setColors } = require('./ipc');

const userDir = app.getPath('userData');

let isConfigDir = fs.existsSync(path.join(userDir, 'config'));
let isSizeDir = fs.existsSync(path.join(userDir, 'config/size.json'))
let isPosDir = fs.existsSync(path.join(userDir, 'config/pos.json'));
let isColorDir = fs.existsSync(path.join(userDir, 'config/colors.json'));

//create config dir if not already exists
if(!isConfigDir){
    fs.mkdirSync(path.join(userDir, '/config'))
}

//check and create config files if not already exist
let pos;
if(!isPosDir){
    let pos_ = {"x":636,"y":0};
    fs.writeFileSync(path.join(userDir, 'config/pos.json'), JSON.stringify(pos_));
    pos = pos_
}else{
    pos = JSON.parse(fs.readFileSync(path.join(userDir, 'config/pos.json'), "utf8"))
}

let size
if(!isSizeDir){
    let size_ = {"width":701,"height":768}
    fs.writeFileSync(path.join(userDir, 'config/size.json'), JSON.stringify(size_));
    size = size_;
}else{
    size = JSON.parse(fs.readFileSync(path.join(userDir, 'config/size.json'), "utf8"))
}

ipcMain.handle("getColors", (event, args)=>{
    let colors;
    if(!isColorDir){
        let colors_ = {"bg":"gold","text":"#000"}
        fs.writeFileSync(path.join(userDir, 'config/colors.json'), JSON.stringify(colors_));
        colors = colors_
        return colors;
    }else{
        colors = JSON.parse(fs.readFileSync(path.join(userDir, 'config/colors.json'), "utf8"));
        return colors;
    }
})

let win;
function createWin(){
    win = new BrowserWindow({
        width:size.width,
        height: size.height,
        x: pos.x,
        y: pos.y,
        title: 'BMS',
        webPreferences:{
            preload: path.join(__dirname, "preload.js")
        }
    });
    isDev ? win.loadURL('http://localhost:3000') : win.loadFile('views/build/index.html')

    win.on("closed", ()=>win = null);

    // set window size in file size.json when the system resized
    win.on('resized', ()=>{
        let size = {
            width: win.getBounds().width,
            height: win.getBounds().height,
        }
        fs.writeFileSync(path.join(userDir, 'config/size.json'), JSON.stringify(size))
    })

    // set window position in file size.json when the window moves
    win.on('move', ()=>{
        let pos = {
            x: win.getBounds().x,
            y: win.getBounds().y
        }
        fs.writeFileSync(path.join(userDir, 'config/pos.json'), JSON.stringify(pos))
    })
}

app.on("ready", ()=>{
    //create window
    createWin();

    setColors(userDir)

})

app.on("window-all-closed", ()=>{
    if(process.platform !== 'darwin'){
        app.quit()
    }
})
app.on('active', ()=>{
    if(win===null){
        createWin()
    }
})


问:
Does Instruction Decoder check a mode bit and makes a interrupt?
I learned that a Privileged Instruction is only executed when current privileged level(CPL) is kernel mode and if not a interrupt is occurred.

And the way to check the current CPL is looking up some mode bit in registers.

I think there should be some process that check a instruction with a mode bit using some special table. And I read this process is on decode state in an unverified blog.

It is true? If not where this process is done?

I wonder where mode bits be checked.

答: Privileged Instructions are defined by CPU but operating-system.It uses a different branch to run,and hardware will do it.To be honest,you should check Intel Software Developer's Manual,but internel process is not public.</p>


问:
In etcd, how do follower campaign only if the follower have the latest data?
For example imagine the case where I only want a follower to be eligible to become a leader only if the follower have the latest data.

Is there a way to do that in etcd?

答: It is etcd's (or rather raft's) guarantee that every new leader will contain all committed entries, where committed entre is one that was replicated to majority of nodes in the cluster. More reading in raft paper, 5.4 Safety


问:
php conditionals
I'm having some trouble understanding how PHP parses conditionals.

For instance,

```<code>while (list($id, $name, $salary) = mysql_fetch_row($result)) { ...}
</code>```

(http://php.net/manual/en/function.list.php )

will evaluate true while the list can retrieve values. But printing the list will print the values contained within the list's variables. The manual also says that list() returns an array. How then, does the conditional know that the mysql fetch attempt was successful?

If it does return a boolean, how do you display it directly rather than

```<code>if(expr) echo 'true';
</code>```

thanks!

答:
list() assigns null to the variables listed if assigned a non-array or an array with too few items.

As null evaluates to false and an array with more than one item evaluates to true, the while loop is able to use the expression.

Small update

list() will trigger an "undefined index" E_NOTICE error if the array does not contain enough items

Title: php conditionals

Body:
I'm having some trouble understanding how PHP parses conditionals.

For instance,

while (list($id, $name, $salary) = mysql_fetch_row($result)) { ...}

(http://php.net/manual/en/function.list.php )

will evaluate true while the list can retrieve values. But printing the list will print the values contained within the list's variables. The manual also says that list() returns an array. How then, does the conditional know that the mysql fetch attempt was successful?

If it does return a boolean, how do you display it directly rather than

if(expr) echo 'true';

thanks!


问:
directly get svf from BIM360 hub/project/model
instead of using Model Derivative, is it possible to get file in SVF format directly from BIM360 model which has already been converted to SVF or SVF2 format? I mean not using MD service at all, thanks.</p>

答:
To download SVF dataset (no matter from your own bucket, or from BIM360), you need to use Forge Derivative API to get manifest (GET:manifest)  info and metadata (GET:Metadata) info. The info will tell the relative cloud path of the *.svf, while *.svf stores the index of the dataset. Then download them one by one.

We have a few code that demo how to download SVF data to local. The most updated one I would recommend is my colleague Petr composed:
https://github.com/petrbroz/forge-convert-utils
It targets to convert SVF to glTF, but it has quite a few granule modules, one of which can download SVF data.

you could perform a simple test:

download the source code of the tool

run npm install

run npm run-script build

export your Forge client id and secret to env

run node samples/download-svf.js <your model urn of BIM360> <local path>

It will start the process to get manifest and download the SVF data one by one to local. This is a screenshot with my test. If you work with js, typescript, you could merge the module to your workflow.


问:
Are incoming webhooks available to all Google chat users or just users with Google Workspace access?
I am currently a free user of Google chat, and I am trying to set up an incoming webhook to send myself asynchronous messages (notifications) in a chat space. I have not been able to locate the "Manage webhooks" dialog in the chat space menu. Is the incoming webhook chat bot feature for Google Chat only available for user with Google Workspace access?</p>

答:
The documentaiton is not very clear about it, but to add a webhook, you should be able to create it first

The documentation for Google Apps Script bot specifies:

Prerequisites

A Google Workspace account with access to Google Chat.

There is no direct respective mention for Webhooks, but this seems to be a bug - see There is no mention in the documentation of the "Configure webhooks" being available only for Workspace users.

In other words:

Unfortunately, Incoming Webhooks are only available to Google Workspace users, even if it is currently not mentioned in the documentation.


问:
UTF8Encode different result on different systems (UTF8Decode)
I ran into an interesting anomaly. I receive a WideString text via RPC, which I need to convert to ANSIString and check the signature in the text against the hash of the text.

On English based Windows (the signature generating server is also English based) it works fine, but on other base language systems (so far it has happened in Russian and Turkish) there are discrepancies.

I have made a simple little test sample to filter out the problematic parts and I noticed that on different systems the UTF8Encode function returns different values for the Unicode characters (the Latin characters are of course fine).

The results are as follows:

```<code>System language       | English                  | Russian
----------------------------------------------------------------------------------
Unicode               | Baйкальская              | Baйкальская
Character codes (ORD) | 1041 1072 1081 1072 1083 | 1041 1072 1081 1072 1083
                      | 1100 1089 1082 1072 1103 | 1100 1089 1082 1072 1103
----------------------------------------------------------------------------------
UTF8Encode            | Ð'Ð°Ð¹ÐºÐ°Ð "ÑŒÑÑÑÐºÐ°Ñ  | Р'Р°Р№РєР°Р "СЊСЃРєР°СЏ
Character codes (ORD) | 208 8216 208 176 208 185 | 1056 8216 1056 176 1056 8470
                      | 208 186 208 176 208 187  | 1056 1108 1056 176 1056 187
                      | 209 338 209 129 208 186  | 1057 1034 1057 1027 1056 1108
                      | 208 176 209 143          | 1056 176 1057 1039
</code>```

The UTF8 encoded characters above were generated using the UTF8Encode function in System, but I also tried the UnicodeToUTF8 function in the Tnt library. Tnt has the option to set the codepage, but if you set a codepage other than UTF8 (or UTF7) the encode does not work.

Whatever I tried, in all cases the above results came out on both systems (or sometimes I got back an empty string in both places when playing with the codepage).

Google searches have not yielded any results either. Although there were some issues with unicode behaving differently on different systems, the only place where there was a solution was to set the encoding of the file containing the unicode.

One more piece of info: the resulting string does not contain a BOM, and the signing program is not homemade, so I cannot modify it.

Any ideas? Suggestion?

Thanks in advance for your help.

Edit:

For numeric values greater than 255... I display the unicode and the encoded result in the same Tnt (Unicode) memo, and the unicode component converts the ANSI to widestring, that's why these numbers come out. I have now converted the display to a plain ANSI memo so that it really shows ANSI characters. Below is the result (bold highlights the change):

```<code>System language       | English                       | Russian
-------------------------------------------------------------------------------------
Unicode               | Baйкальская                   | Baйкальская
Character codes (ORD) | 1041 1072 1081 1082 1072 1083 | 1041 1072 1081 1082 1072 1083
                      | 1100 1089 1082 1072 1103      | 1100 1089 1082 1072 1103
-------------------------------------------------------------------------------------
UTF8Encode            | Ð'Ð°Ð¹ÐºÐ°Ð°Ð "ÑŒÑÐºÐ°Ñ       | Ð'Ð°Ð¹ÐºÐ°Ð°Ð "ÑŒÑÐºÐ°Ñ
Character codes (ORD) | 208 145 208 176 208 185       | 208 145 208 176 208 185
                      | 208 186 208 176 208 187       | 208 186 208 176 208 187
                      | 209 140 209 129 208 186       | 209 140 209 129 208 186
                      | 208 176 209 143               | 208 176 209 143
</code>```

But it's not just the numbers that are under 255 (and they now match perfectly on both sides)... in the Russian system, the text starting with P appeared visually in the ANSI memo, but when I copied and pasted it in the English system, the text starting with Ð appeared. The same in reverse, if I copy it from here to the memo of the program running on the Russian system, the one beginning with P appears (paste to the russian notepad shows text starting with Ð).

Edit 2:

Well, back to basics... After it turned out that UTF8Encode produced exactly the same result, I went ahead and looked at the signature validator part of the signature validator function. I wrote out the part to be signed and saw that instead of unicode characters, there are just question marks (in ANSI memo of course, in Unicode of course the original unicode text is displayed).

I'm working in Delphi 7, but the core system can be used in Delphi RAD too, the signature validator is set up with compile directives to handle the difference between the two IDE separately for the string type. Under Delphi 7 it encodes first (I thought this was the problem so far), then decodes back to WideString before validating (obviously it doesn't do these under RAD).

I had a thought and deleted UTF8Decode from the Delphi 7 code fragment... After that the Encode version of the string appeared, but the signature is not valid. Normal, since it was signed on the decoded text.

And here comes the difference... In English the Russian text is unicode, so after the Encode/Decode the original unicode text comes back. However, in Russian, the original unicode Russian text after Encode/Decode picks up the corresponding value between 128 and 255 based on the Russian code page. Which is no longer the original unicode value.

In any case, I need to modify the system so that it does not Encode/Decode, and the problem will be solved.

答:
There's something with your implementation/interpretation. Your UTF-8 is not UTF-8 (as can be seen by the values being 16-bit and not 8-bit in most cases).

EDIT: A later comment showed that the OP is using Delphi7, so the below doesn't apply. However, it applies to all Unicode versions of Delphi from D2009 onward...

Try this code on a Button OnClick event:

PROCEDURE TForm102.Button1Click(Sender: TObject);
  VAR
    S,M : STRING;
    U   : UTF8String;
    C   : CHAR;
    UC  : UTF8Char;

  BEGIN
    S:='Baйкальская'; // Note "Ba" at the beginning is ASCII characters - is that correct?
    U:=S;
    M:='UTF-16:';
    FOR C IN S DO M:=M+' '+IntToHex(Ord(C),4);
    M:=M+#13#10'UTF-8:';
    FOR UC IN U DO M:=M+' '+IntToHex(Ord(UC),2);
    MessageDlg(M,TMsgDlgType.mtInformation,[mbOK],0)
  END;
```
<p>On my PC, it displays this result:</p>
<pre class="lang-none prettyprint-override"><code>UTF-16: 0042 0061 0439 043A 0430 043B 044C 0441 043A 0430 044F
UTF-8: 42 61 D0 B9 D0 BA D0 B0 D0 BB D1 8C D1 81 D0 BA D0 B0 D1 8F
</code>```

Which is the correct UTF-8 encoding of the UTF-16 string. There's no such thing as code pages in UTF-8 (or UTF-16), AFAIK, so you're barking up the wrong tree.

The easiest way to obtain a UTF-8 string from a UTF-16 string is simply to declare a variable of type UTF8String and use assignment from a UnicodeString or WideString. Delphi does the conversion for you.

Just remember that UTF-16 uses 16-bit characters, and UTF-8 uses 8-bit characters.  Don't try to use AnsiString - that one is CodePage-dependant and will screw you over if you try to use it to store a UTF-8 string. If you MUST use an 8-bit string, use RawByteString instead, or - even better - forego strings altogether and use a TBytes instead:

VAR
  UTF8 : TBytes;
  S    : STRING;
  ...
  UTF8:=TEncoding.UTF8.GetBytes(S);
  ...
```

Body:
I ran into an interesting anomaly. I receive a WideString text via RPC, which I need to convert to ANSIString and check the signature in the text against the hash of the text.

On English based Windows (the signature generating server is also English based) it works fine, but on other base language systems (so far it has happened in Russian and Turkish) there are discrepancies.

I have made a simple little test sample to filter out the problematic parts and I noticed that on different systems the UTF8Encode function returns different values for the Unicode characters (the Latin characters are of course fine).

The results are as follows:

System language       | English                  | Russian
----------------------------------------------------------------------------------
Unicode               | Baйкальская              | Baйкальская
Character codes (ORD) | 1041 1072 1081 1072 1083 | 1041 1072 1081 1072 1083
                      | 1100 1089 1082 1072 1103 | 1100 1089 1082 1072 1103
----------------------------------------------------------------------------------
UTF8Encode            | Ð'Ð°Ð¹ÐºÐ°Ð "ÑŒÑÑÑÐºÐ°Ñ  | Р'Р°Р№РєР°Р "СЊСЃРєР°СЏ
Character codes (ORD) | 208 8216 208 176 208 185 | 1056 8216 1056 176 1056 8470
                      | 208 186 208 176 208 187  | 1056 1108 1056 176 1056 187
                      | 209 338 209 129 208 186  | 1057 1034 1057 1027 1056 1108
                      | 208 176 209 143          | 1056 176 1057 1039

The UTF8 encoded characters above were generated using the UTF8Encode function in System, but I also tried the UnicodeToUTF8 function in the Tnt library. Tnt has the option to set the codepage, but if you set a codepage other than UTF8 (or UTF7) the encode does not work.

Whatever I tried, in all cases the above results came out on both systems (or sometimes I got back an empty string in both places when playing with the codepage).

Google searches have not yielded any results either. Although there were some issues with unicode behaving differently on different systems, the only place where there was a solution was to set the encoding of the file containing the unicode.

One more piece of info: the resulting string does not contain a BOM, and the signing program is not homemade, so I cannot modify it.

Any ideas? Suggestion?

Thanks in advance for your help.

Edit:

For numeric values greater than 255... I display the unicode and the encoded result in the same Tnt (Unicode) memo, and the unicode component converts the ANSI to widestring, that's why these numbers come out. I have now converted the display to a plain ANSI memo so that it really shows ANSI characters. Below is the result (bold highlights the change):

System language       | English                       | Russian
-------------------------------------------------------------------------------------
Unicode               | Baйкальская                   | Baйкальская
Character codes (ORD) | 1041 1072 1081 1082 1072 1083 | 1041 1072 1081 1082 1072 1083
                      | 1100 1089 1082 1072 1103      | 1100 1089 1082 1072 1103
-------------------------------------------------------------------------------------
UTF8Encode            | Ð'Ð°Ð¹ÐºÐ°Ð°Ð "ÑŒÑÐºÐ°Ñ       | Ð'Ð°Ð¹ÐºÐ°Ð°Ð "ÑŒÑÐºÐ°Ñ
Character codes (ORD) | 208 145 208 176 208 185       | 208 145 208 176 208 185
                      | 208 186 208 176 208 187       | 208 186 208 176 208 187
                      | 209 140 209 129 208 186       | 209 140 209 129 208 186
                      | 208 176 209 143               | 208 176 209 143

But it's not just the numbers that are under 255 (and they now match perfectly on both sides)... in the Russian system, the text starting with P appeared visually in the ANSI memo, but when I copied and pasted it in the English system, the text starting with Ð appeared. The same in reverse, if I copy it from here to the memo of the program running on the Russian system, the one beginning with P appears (paste to the russian notepad shows text starting with Ð).

Edit 2:

Well, back to basics... After it turned out that UTF8Encode produced exactly the same result, I went ahead and looked at the signature validator part of the signature validator function. I wrote out the part to be signed and saw that instead of unicode characters, there are just question marks (in ANSI memo of course, in Unicode of course the original unicode text is displayed).

I'm working in Delphi 7, but the core system can be used in Delphi RAD too, the signature validator is set up with compile directives to handle the difference between the two IDE separately for the string type. Under Delphi 7 it encodes first (I thought this was the problem so far), then decodes back to WideString before validating (obviously it doesn't do these under RAD).

I had a thought and deleted UTF8Decode from the Delphi 7 code fragment... After that the Encode version of the string appeared, but the signature is not valid. Normal, since it was signed on the decoded text.

And here comes the difference... In English the Russian text is unicode, so after the Encode/Decode the original unicode text comes back. However, in Russian, the original unicode Russian text after Encode/Decode picks up the corresponding value between 128 and 255 based on the Russian code page. Which is no longer the original unicode value.

In any case, I need to modify the system so that it does not Encode/Decode, and the problem will be solved.

Body:
There's something with your implementation/interpretation. Your UTF-8 is not UTF-8 (as can be seen by the values being 16-bit and not 8-bit in most cases).

EDIT: A later comment showed that the OP is using Delphi7, so the below doesn't apply. However, it applies to all Unicode versions of Delphi from D2009 onward...

Try this code on a Button OnClick event:

PROCEDURE TForm102.Button1Click(Sender: TObject);
  VAR
    S,M : STRING;
    U   : UTF8String;
    C   : CHAR;
    UC  : UTF8Char;

  BEGIN
    S:='Baйкальская'; // Note "Ba" at the beginning is ASCII characters - is that correct?
    U:=S;
    M:='UTF-16:';
    FOR C IN S DO M:=M+' '+IntToHex(Ord(C),4);
    M:=M+#13#10'UTF-8:';
    FOR UC IN U DO M:=M+' '+IntToHex(Ord(UC),2);
    MessageDlg(M,TMsgDlgType.mtInformation,[mbOK],0)
  END;

On my PC, it displays this result:

UTF-16: 0042 0061 0439 043A 0430 043B 044C 0441 043A 0430 044F
UTF-8: 42 61 D0 B9 D0 BA D0 B0 D0 BB D1 8C D1 81 D0 BA D0 B0 D1 8F

Which is the correct UTF-8 encoding of the UTF-16 string. There's no such thing as code pages in UTF-8 (or UTF-16), AFAIK, so you're barking up the wrong tree.

The easiest way to obtain a UTF-8 string from a UTF-16 string is simply to declare a variable of type UTF8String and use assignment from a UnicodeString or WideString. Delphi does the conversion for you.

Just remember that UTF-16 uses 16-bit characters, and UTF-8 uses 8-bit characters.  Don't try to use AnsiString - that one is CodePage-dependant and will screw you over if you try to use it to store a UTF-8 string. If you MUST use an 8-bit string, use RawByteString instead, or - even better - forego strings altogether and use a TBytes instead:

VAR
  UTF8 : TBytes;
  S    : STRING;
  ...
  UTF8:=TEncoding.UTF8.GetBytes(S);
  ...


问:
Updating from Angular11 to 13 generates error Data path "" must NOT have additional properties(styleext)
I have checked out the following prescriptions for this problem and they did not resolve my issue. I upgraded from angular 11 to 13 following the procedure on the Angular official website which went well. Then Itried to generate a component and the issues started.</p>

答: Run this at the command prompt: "ng config -g schematics.@schematics/angular:component.styleext undefined"</p>


问:
SUM with WHERE col IN and COUNT of GROUP BY subquery = funny math
I'm trying to get the total count of each GROUP where two words are used on a page together. For example, I have a word that appears 83 times on is own and another word that appears 22 times on its own, but within the same group (GROUP BY Book, Chapter, Page) they appear together 2 times, so I expect to get 2 from my query::

```<code>"SELECT SUM(pagetotal) AS total
FROM
(SELECT COUNT(DISTINCT Page) AS pagetotal
FROM Books
WHERE Word IN ('Apples', 'Oranges')
GROUP BY BookID, Chapter, Page
) AS t ";
</code>```

This gives me a SUM of 103, which is clearly the opposite of what I want (it seems to be adding the individual usages of the word "Apples" (83) with that of "Oranges" (22), then SUBTRACTING the two pages where they're used together!) I've tried it with other entries in the column together and get the same result. What am I missing?

答:
GROUP BY BookID, Chapter, Page gives you one result row per book page. COUNT(DISTINCT Page) tells you how many pages are in the page, which is one, the page itself, obviously. You then add up all those ones to get the total number of pages one of the words exists in.

What you seem to want instead is the pages where both words appear in, for which you count them individually per page:

```<code>SELECT
  BookID, Chapter, Page,
  COUNT(CASE WHEN Word = 'Apples' THEN 1 END) as apples,
  COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) as oranges,
  COUNT(*) AS total
FROM Books
WHERE Word IN ('Apples', 'Oranges')
GROUP BY BookID, Chapter, Page
HAVING COUNT(CASE WHEN Word = 'Apples' THEN 1 END) > 0
   AND COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) > 0
ORDER BY BookID, Chapter, Page;
</code>```

If you just want the number of pages where both words occur together:

```<code>SELECT COUNT(*)
FROM
(
  SELECT BookID, Chapter, Page,
  FROM Books
  WHERE Word IN ('Apples', 'Oranges')
  GROUP BY BookID, Chapter, Page
  HAVING COUNT(CASE WHEN Word = 'Apples' THEN 1 END) > 0
     AND COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) > 0
) pages_with_both_words;
</code>```

The message of using CASE WHEN inside an aggreagtion function, as in COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) is called conditional aggregation by the way. The standard SQL for this is:

```<code>COUNT(*) FILTER (WHERE Word = 'Oranges')
</code>```

but only few DBMS support this, yet.

Body:
I'm trying to get the total count of each GROUP where two words are used on a page together. For example, I have a word that appears 83 times on is own and another word that appears 22 times on its own, but within the same group (GROUP BY Book, Chapter, Page) they appear together 2 times, so I expect to get 2 from my query::

"SELECT SUM(pagetotal) AS total
FROM
(SELECT COUNT(DISTINCT Page) AS pagetotal
FROM Books
WHERE Word IN ('Apples', 'Oranges')
GROUP BY BookID, Chapter, Page
) AS t ";

This gives me a SUM of 103, which is clearly the opposite of what I want (it seems to be adding the individual usages of the word "Apples" (83) with that of "Oranges" (22), then SUBTRACTING the two pages where they're used together!) I've tried it with other entries in the column together and get the same result. What am I missing?

Body:
GROUP BY BookID, Chapter, Page gives you one result row per book page. COUNT(DISTINCT Page) tells you how many pages are in the page, which is one, the page itself, obviously. You then add up all those ones to get the total number of pages one of the words exists in.

What you seem to want instead is the pages where both words appear in, for which you count them individually per page:

SELECT
  BookID, Chapter, Page,
  COUNT(CASE WHEN Word = 'Apples' THEN 1 END) as apples,
  COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) as oranges,
  COUNT(*) AS total
FROM Books
WHERE Word IN ('Apples', 'Oranges')
GROUP BY BookID, Chapter, Page
HAVING COUNT(CASE WHEN Word = 'Apples' THEN 1 END) > 0
   AND COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) > 0
ORDER BY BookID, Chapter, Page;

If you just want the number of pages where both words occur together:

SELECT COUNT(*)
FROM
(
  SELECT BookID, Chapter, Page,
  FROM Books
  WHERE Word IN ('Apples', 'Oranges')
  GROUP BY BookID, Chapter, Page
  HAVING COUNT(CASE WHEN Word = 'Apples' THEN 1 END) > 0
     AND COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) > 0
) pages_with_both_words;

The message of using CASE WHEN inside an aggreagtion function, as in COUNT(CASE WHEN Word = 'Oranges' THEN 1 END) is called conditional aggregation by the way. The standard SQL for this is:

COUNT(*) FILTER (WHERE Word = 'Oranges')

but only few DBMS support this, yet.


问:
Passing array into query string
I need to send array as query parameter, I do it like this

```<code>StringBuilder Ids = new StringBuilder();
for (int i = 0; i < array.Count; i++)
{
    Ids.Append(String.Format("&id[{0}]={1}", i, items[i].ID));
}

ifrDocuments.Attributes.Add("src", "Download.aspx?arrayCount=" + array.Count + Ids);
</code>```

After this I have string:

```<code>Download.aspx?arrayCount=8&id[0]=106066&id[1]=106065&id[2]=106007&id[3]=105284&id[4]=105283&id[5]=105235&id[6]=105070&id[7]=103671
</code>```

It can contain 100 elements and in this case I'm getting error:

enter image description here

Maybe I can do it in another way? Not by sending it inside query qtring.

答:
QueryString is not the way to pass an array because of the limits.
If you have hands on the endpoint, you should consider sending your array in a POST Body.

Regards

Title: Passing array into query string

Body:
I need to send array as query parameter, I do it like this

StringBuilder Ids = new StringBuilder();
for (int i = 0; i < array.Count; i++)
{
    Ids.Append(String.Format("&id[{0}]={1}", i, items[i].ID));
}

ifrDocuments.Attributes.Add("src", "Download.aspx?arrayCount=" + array.Count + Ids);

After this I have string:

Download.aspx?arrayCount=8&id[0]=106066&id[1]=106065&id[2]=106007&id[3]=105284&id[4]=105283&id[5]=105235&id[6]=105070&id[7]=103671

It can contain 100 elements and in this case I'm getting error:

enter image description here

Maybe I can do it in another way? Not by sending it inside query qtring.


问:
iOS Splash Page while Loading Data
I am trying to write an app that displays a simple logo/splash page while the app retrieves some data. I cannot seem to find a tutorial anywhere.

I have a "MainWindow.xib" file that will have my splash page, and I'm setting that as my "Main Interface" in my Info.plist, however, I cannot seem to see how to replace that page with a .xib that contains a UINavigationController. I thought I would just create a new UIController, that had a UINavigationController and in my .xib I'll drag in a Navigation Controller and set all my information, but it's giving me real fits.

So, I figured I would have a UIController that I would "alloc" and "init" with my second .xib that contains all my navigation.

```<code>myMainController = [[UIController alloc] initWithNibName:@"MainNavController":nil];
</code>```

in "MainNavController.xib", I've dragged in a Navigation Controller, but I don't know what to connect it to????

I'm sure I'm going down the wrong, path; but I cannot find a decent tutorial for this.

Can someone give direction or link to a decent tutorial?

Thanks.

答:
To display a splash screen while the app is loading you can use Default.png image file.
However, I think your question is how to display another splash screen for a period of time after the app has been loaded.
In you MainWindow.xib keep your window separated from your Navigation Controller. Add your splash screen view with an image to the xib.
Make two outlets: one for slash view, one for Navigation Controller.

```<code>IBOutlet UIView* _spashScreenView;
IBOutlet UINavigationController* _navigationController;
</code>```

In applicationDidFinishLaunching method add your splash screen view to the window.

```<code>[_window addSubview:_spashScreenView];
// lay it out
</code>```

When you are ready to display your navigation controller:

```<code>[_spashScreenView removeFromSuperView];
[_window addSubview:_navigationController];
</code>```

Title: iOS Splash Page while Loading Data

Body:
I am trying to write an app that displays a simple logo/splash page while the app retrieves some data. I cannot seem to find a tutorial anywhere.

I have a "MainWindow.xib" file that will have my splash page, and I'm setting that as my "Main Interface" in my Info.plist, however, I cannot seem to see how to replace that page with a .xib that contains a UINavigationController. I thought I would just create a new UIController, that had a UINavigationController and in my .xib I'll drag in a Navigation Controller and set all my information, but it's giving me real fits.

So, I figured I would have a UIController that I would "alloc" and "init" with my second .xib that contains all my navigation.

myMainController = [[UIController alloc] initWithNibName:@"MainNavController":nil];

in "MainNavController.xib", I've dragged in a Navigation Controller, but I don't know what to connect it to????

I'm sure I'm going down the wrong, path; but I cannot find a decent tutorial for this.

Can someone give direction or link to a decent tutorial?

Thanks.

Body:
To display a splash screen while the app is loading you can use Default.png image file.
However, I think your question is how to display another splash screen for a period of time after the app has been loaded.
In you MainWindow.xib keep your window separated from your Navigation Controller. Add your splash screen view with an image to the xib.
Make two outlets: one for slash view, one for Navigation Controller.

IBOutlet UIView* _spashScreenView;
IBOutlet UINavigationController* _navigationController;

In applicationDidFinishLaunching method add your splash screen view to the window.

[_window addSubview:_spashScreenView];
// lay it out

When you are ready to display your navigation controller:

[_spashScreenView removeFromSuperView];
[_window addSubview:_navigationController];


问:
Json serialization with timezone
I have a json like this

```<code>{
    ...
    "date":"2022-02-28T00:00:00+01:00"
    ...
}
</code>```

and the JsonSerializerSettings

```<code>new JsonSerializerSettings
{
    Formatting = Formatting.None,
    NullValueHandling = NullValueHandling.Ignore,
});
</code>```

when the json is deserialized in the class that contain the date property the value is 2022-02-27 at 23:00.
How should I change JsonSerializerSettings to get the same value in the object, so 2022-02-28?

答:
By default, NewtonsoftJson parses to a DateTime, which doesn't contain timezone information. But you can set the DateParseHandling option to DateTimeOffset instead (list of possible options for the setting here). DateTimeOffset is a type that includes timezone information.

So:

```<code>new JsonSerializerSettings
{
    Formatting = Formatting.None,
    NullValueHandling = NullValueHandling.Ignore,
    DateParseHandling = DateParseHandling.DateTimeOffset,
});
</code>```

Title: Json serialization with timezone

Body:
I have a json like this

{
    ...
    "date":"2022-02-28T00:00:00+01:00"
    ...
}

and the JsonSerializerSettings

new JsonSerializerSettings
{
    Formatting = Formatting.None,
    NullValueHandling = NullValueHandling.Ignore,
});

when the json is deserialized in the class that contain the date property the value is 2022-02-27 at 23:00.
How should I change JsonSerializerSettings to get the same value in the object, so 2022-02-28?

Body:
By default, NewtonsoftJson parses to a DateTime, which doesn't contain timezone information. But you can set the DateParseHandling option to DateTimeOffset instead (list of possible options for the setting here). DateTimeOffset is a type that includes timezone information.

So:

new JsonSerializerSettings
{
    Formatting = Formatting.None,
    NullValueHandling = NullValueHandling.Ignore,
    DateParseHandling = DateParseHandling.DateTimeOffset,
});