.NET 3.5 PresentationCore Crash on Startup on Windows 11

Hi there,

If you are having a startup crash on your WPF application. With .NET 3.5 framework and on Windows 11. Also with this log on Event Viewer.

Fault bucket 2160294874680227364, type 5
Event Name: CLR20r3
Response: Not available
Cab Id: 0

Problem signature:
P1: itcapplauncher.exe // <– This is my app
P2: 1.0.0.0
P3: 8a01dbfb
P4: PresentationCore
P5: 3.0.0.0
P6: 6090bfa0
P7: 21db
P8: a
P9: System.NullReferenceException
P10:

My fix here is to move the .net framework higher than 3.5, I moved it to .NET framework 4. This is so I can still be compatible with windows XP.

Sorry my suggestion is a little unacceptible with other coders but I do not have a choice since the issue of crashing is outside my source code.

Happy Coding!

C#/WPF/MVVM/Web API Properly stream/download files from .NET Web API and display progress through progress bar

1. Setup .NET Web API code.

namespace MainWebService.Controllers
{
 
    [ApiController]
    [Route("[controller]")]
    public class BuildController : ControllerBase
    {        
 
        [HttpPost]
        [Route("[action]")]
        public Stream GetFile([FromBodyStringParamEntity parameters)
        {
            FileStream stream = System.IO.File.OpenRead(Path.Combine(System.IO.Directory.GetCurrentDirectory(), parameters.ParamString));
            return stream;
 
        }
 
    }
}

Nevermind the parameter for the method. Basically what the snippet says is you create a [FileStream] object and return it. You can you its base class [Stream] as the return type of the method.

2. Consume through HttpRequestMessage

public static async Task<StreamCommonHTTPClientCodeForFileTransfer(HttpClient clientstring baseURLstring webMethodStringParamEntity parameters)
{
 
    try
    {
 
        HttpResponseMessage hrm = await ReturnHttpStream(clientbaseURLwebMethodparameters);
        return await hrm.Content.ReadAsStreamAsync();
 
    }
    catch(Exception ex)
    {
 
        Exception newEx = new Exception(ErrorMessageConstant.HTTP_CLIENT_FILE_STREAM_ERROR_MESSAGE, ex);
        throw newEx;
 
    }
 
}
 
private static Task<HttpResponseMessageReturnHttpStream(HttpClient clientstring baseURLstring webMethodStringParamEntity parameters)
{
 
 
 
    string requestUrl = new Uri(new Uri(baseURL), webMethod).ToString();
 
    JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
    {
        DateFormatString = Constant.MY_DATETIME_FORMAT,
        DateFormatHandling = DateFormatHandling.IsoDateFormat
    };
 
    string
        jsonData =
            JsonConvert.SerializeObject
                (
                    parameters,
                    microsoftDateFormatSettings
                );
 
    client.DefaultRequestHeaders.Accept.Clear();
 
    
    ifparameters.ParamString.IndexOf(".dll"StringComparison.CurrentCultureIgnoreCase) > 0 )
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-msdownload"));
    if (parameters.ParamString.IndexOf(".exe"StringComparison.CurrentCultureIgnoreCase) > 0)
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
    if (parameters.ParamString.IndexOf(".zip"StringComparison.CurrentCultureIgnoreCase) > 0)
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/zip"));
 
    var request = new StringContent(jsonDataEncoding.UTF8, "application/json");
    
 
    using (HttpRequestMessage rm = new HttpRequestMessage(HttpMethod.Post, requestUrl))
    {
        rm.Content = request;
        return client.SendAsync(rmHttpCompletionOption.ResponseHeadersRead);
    }
 
 
}

Use the class instance of HttpRequestMessage instead of HttpClient. Use the HttpCompletion.ResponseHeadersRead enum argument for the second parameter of its SendAsync method. This is a key setting that will properly allow every byte to be recognized in the stream(in real time). Either this argument is not used or you went to using a different class (HttpClient) anyway it will not work, the file will be downloaded completely even before iterating per byte in the stream instance at the client side.

Nevermind the other code that is for the settings of JSON serialization.

3. WPF XAML

<StackPanel Grid.Row="1" Orientation="Vertical">
        <TextBlock Text="{Binding StatusText}"></TextBlock>
        <ProgressBar Minimum="0" Maximum="100" Name="pbStatus" Value="{Binding ByteTransfered}"></ProgressBar>
</StackPanel>

Create the progress bar element and have the integer Value property binded to the View Model.

4. Finally, ViewModel code.

Task<StreamtStream = CommonFunctions.CommonHTTPClientCodeForFileTransfer
(
    client,
    reg.DataSourceURLPath,
    "Build/GetFile",
    param2
);
 
await tStream;
 
Stream st = tStream.Result;
 
int length = f.ByteSize;
byte[] result = new byte[length];
 
StatusText = f.FileName;
 
string destinationPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constant.STEP_ASIA_MIS_INSTALLATION_FOLDER, f.FileName);
 
byte[] bytes = new byte[length + 100000];
int numBytesToRead = (int)length;
int numBytesRead
do
{
    int n = await st.ReadAsync(bytesnumBytesRead, 100000);
    numBytesRead += n;
    numBytesToRead -= n;
 
    StatusText = string.Format("{0} {1:0.##}%",  f.FileName,((1.0 * numBytesRead) / length) * 100.0 );
    ByteTransfered = CommonFunctions.ConvertToInt( (1.0 * numBytesRead / length) * 100 );
 
 
} while (numBytesToRead > 0);
 
using (var fs = File.Create(destinationPath))
{
    fs.Write(bytes, 0, length);
}

Hope you learned.

WPF – Touchdown event firing at overlapping controls.

This happens when a button or link behind another button or link is getting its touchdown event fired as well.

The fix here:

1. Make sure tap event of both controls are subscribed on the Touchdown event.
2. Put a e.Handled = true; statement inside the eventhandler of the overlapping control.

Example:

Code Snippet
  1. private void OpenDoctor_Touch(object sender, TouchEventArgs e)
  2. {
  3.     e.Handled = true;
  4.     string commandParameter = ((Button)sender).CommandParameter.ToString();
  5.     var viewModel = (DoctorsBySpecializationViewModel)DataContext;
  6.     if (viewModel.OpenDoctor.CanExecute(commandParameter))
  7.         viewModel.OpenDoctor.Execute(commandParameter);
  8. }

Happy Coding!

WPF and MVVM – Touch Device needs to tap twice on button to fire command.

Touch devices may need to tap twice on a button to fire command.

This always happens on my end when the button is located alongside a textbox or other elements on a user or windows control.

The fix.

1. Add a touch down event for the event in the xaml.

2. Fire command manually

            MapEntity commandParameter = (MapEntity)(((Button)sender).CommandParameter);

            var viewModel = (FindADISViewModel)DataContext;
            if (viewModel.OpenDIS.CanExecute(commandParameter))
                viewModel.OpenDIS.Execute(commandParameter);

It works!