asynchronous load ImagePart data error - asynchronous

I use DocumentFormat.OpenXml for generating docx. I try to load small png images (20-50 kb) to my docx asynchronously from WebClient. And I have different result for one code:
No problem
NullReferenceException
FileFormatException
ObjectDisposedException
InvalidOperationException
This code demonstrates my problem:
internal class Program
{
public static void Main(string[] args)
{
using (var outputStream = new MemoryStream())
{
using (var doc = WordprocessingDocument.Create(outputStream, WordprocessingDocumentType.Document))
{
var mainPart = doc.AddMainDocumentPart();
new Document(new Body()).Save(mainPart);
var tasks = Directory.GetFiles("images").Select(async it =>
await AddImagePart(it, mainPart.AddImagePart(ImagePartType.Png)).ConfigureAwait(false));
Task.WaitAll(tasks.ToArray());
}
File.WriteAllBytes("output.docx", outputStream.ToArray());
}
}
private static async Task AddImagePart(string path, ImagePart imagePart)
{
using (var client = new WebClient())
{
var image = await client.DownloadDataTaskAsync(path).ConfigureAwait(false);
imagePart.FeedData(new MemoryStream(image));
}
}
packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DocumentFormat.OpenXml" version="2.7.2" targetFramework="net46" />
<package id="System.IO.FileSystem.Primitives" version="4.0.1" targetFramework="net46" />
<package id="System.IO.Packaging" version="4.0.0" targetFramework="net46" />
</packages>
There are described on git problem with large files and .net less then 4.6. But I use small files and .net4.6.

Maybe you should read this post about async\await mistakes.
Try to make ConfigureAwait(false).

Related

SignalR .Net Client with MessagePack - AddMessagePackProtocol Method Unrecognised in IHubConnectionBuilder

New user, trying to learn SignalR and Blazor Server, hoping somebody can help with this query. Struggling with getting the SignalR .NET Client to use MessagePack protocol in the Blazor Server Page.
.csproj Packages Installed
<ItemGroup>
<PackageReference Include="Autofac" Version="5.2.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
<!-- <PackageReference Include="MessagePack" Version="1.9.3" /> -->
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.7" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.7" />
</ItemGroup>
Originally I had installed 3.1.8 of SingalR Client and MessagePack packages. However, I have also tried downgrading to 3.1.7 and the issue still occurs.
This segment of code:
hubConnection = new HubConnectionBuilder()
.WithUrl(hubUrl)
.AddMessagePackProtocol()
.Build();
causes a build error:
error CS1061: 'IHubConnectionBuilder' does not contain a definition for 'AddMessagePackProtocol' and no accessible extension method 'AddMessagePackProtocol' accepting a first argument of type 'IHubConnectionBuilder' could be found (are you missing a using directive or an assembly reference?).....
Can anybody help? Am I missing an assembly #using reference?
Blazor Server Page
#page "/"
#using System.Threading;
#using System.Collections.Generic;
#using Microsoft.AspNetCore.SignalR.Client;
#using WebApp.Data;
#inject NavigationManager NavigationManager
<h1>Blazor Server App</h1>
<div>Latest message is => #_latestMessage</div>
<div id="scrollbox">
#foreach (var item in _messages)
{
<div>
<div>#item</div>
</div>
}
<hr />
</div>
#code {
private HubConnection hubConnection;
private string _latestMessage = "";
private List<string> _messages = new List<string>();
public bool IsConnected => hubConnection.State == HubConnectionState.Connected;
protected override async Task OnInitializedAsync()
{
var hubUrl = NavigationManager.BaseUri.TrimEnd('/') + "/motionhub";
// Uri uri = NavigationManager.ToAbsoluteUri("/motionhub");
try
{
hubConnection = new HubConnectionBuilder()
.WithUrl(hubUrl)
.AddMessagePackProtocol()
.Build();
hubConnection.On<string>("SendMotionDetection", ReceiveMessage);
await hubConnection.StartAsync();
Console.WriteLine("Index Razor Page initialised, listening on signalR hub url => " + hubUrl.ToString());
Console.WriteLine("Hub Connected => " + IsConnected);
}
catch (Exception e)
{
Console.WriteLine("Encountered exception => " + e);
}
}
private void ReceiveMessage(string message)
{
try
{
Console.WriteLine("Hey! I received a message");
_latestMessage = message;
_messages.Add(_latestMessage);
StateHasChanged();
}
catch (Exception ex)
{
Console.Error.WriteLine("An exception was encountered => " + ex.ToString());
}
}
}
Finally, got this to compile by adding:
#using Microsoft.Extensions.DependencyInjection;
Hope this saves some time for other new users that experience similar issue.
Just to clarify the correct answer already given by #anon_dc3spp it should be noted that you:
Need to have the Microsoft.AspNetCore.SignalR.Protocols.MessagePack Nuget Package installed on both the client and server.
Then you would use his reference shown below on the intended razor page... or maybe add it to your imports page:
#using Microsoft.Extensions.DependencyInjection

How to get Unity Container from external configuration file?

In asp.net web api using Unity, I could register my services in UnityConfig.cs:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITestService, TestService>();
//above code needs to be read from config file
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Now, I have a configuration file (located in the root of the project) where stores all those types to be registered:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity>
<alias alias="ITestService" type="IMyServices.ITestService, IMyServices" />
<container>
<register type="ITestService" mapTo="MyServices.TestService,MyServices" />
</container>
</unity>
</configuration>
How can I get container from this file?
Below is a similar question but has not been resolved:
ASP.NET - Unity - Read configuration section from external configuration file
I find the solution to my problem which uses ExeConfigurationFileMap to specify the file path and load the specified configuration file explicitly.
public static class UnityConfig
{
public static void RegisterComponents()
{
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "my/file/path";
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var section = (UnityConfigurationSection)configuration.GetSection("unity");
IUnityContainer unityContainer = new UnityContainer();
unityContainer.LoadConfiguration(section);
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(unityContainer);
}
}

Razor engine can't find my view in .Net Core class library

I have my class library, which consists of ViewRenderService class:
public interface IViewRenderService
{
Task<string> RenderToStringAsync(string viewName, object model);
}
public class ViewRenderService : IViewRenderService
{
private readonly IRazorViewEngine _razorViewEngine;
private readonly ITempDataProvider _tempDataProvider;
private readonly IServiceProvider _serviceProvider;
public ViewRenderService(IRazorViewEngine razorViewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider)
{
_razorViewEngine = razorViewEngine;
_tempDataProvider = tempDataProvider;
_serviceProvider = serviceProvider;
}
public async Task<string> RenderToStringAsync(string viewName, object model)
{
var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
using (var sw = new StringWriter())
{
var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);
if (viewResult.View == null)
{
throw new ArgumentNullException($"{viewName} does not match any available view");
}
var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
{
Model = model
};
var viewContext = new ViewContext(
actionContext,
viewResult.View,
viewDictionary,
new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
sw,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return sw.ToString();
}
}
and a lot of views, which start from the path: my class library root/Views//Shared/many views.
The problem is, that IRazorViewEngine can't find my views, how should I call viewRenderService.RenderToStringAsync(?) to render ~/Views/Shared/Myview.cshtml, for example?
The way I handle views in class libraries is to make the views embedded resources, ie in the .csproj file I have
<ItemGroup>
<EmbeddedResource Include="Views\**" Exclude="bin\**;obj\**;**\*.xproj;packages\**;#(EmbeddedResource)" />
</ItemGroup>
and you need this package:
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="1.1.*" />
and then I have an extension method in my class library like this:
public static RazorViewEngineOptions AddCloudscribeSimpleContentBootstrap3Views(this RazorViewEngineOptions options)
{
options.FileProviders.Add(new EmbeddedFileProvider(
typeof(Bootstrap3).GetTypeInfo().Assembly,
"cloudscribe.SimpleContent.Web.Views.Bootstrap3"
));
return options;
}
and then in Startup.cs of the main app you have to opt in to including those views using the extension method like this:
services.AddMvc()
.AddRazorOptions(options =>
{
options.AddCloudscribeSimpleContentBootstrap3Views();
});
Update for ASP.NET Core 2.0
In your library .csproj, you should have the following (everything else mentioning your views can be removed/commented):
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Content Update="Views\xxx\_MyView.cshtml">
<Pack>$(IncludeRazorContentInPack)</Pack>
</Content>
</ItemGroup>
</Project>
Note the Content Update= that replaces a Content Includes=, it gave me some hard time to find what was wrong :)
As well as the .Razor of Project Sdk="Microsoft.NET.Sdk.Razor" which embeds views correctly.
Update for .Net Core 3.1
After struggling for a while myself with the same problem #Jean's answer was of great help. Here's my .Net Core 3.1 update of that answer. Hope it will help other people.
This is in the .csproj file of the .Net Core 3.1 class library:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<Content Update="Views\**\*.cshtml" />
</ItemGroup>
</Project>
This is the file structure in the library.
To invoke the View Component in the library from the web app use this:
#await Component.InvokeAsync("GoogleAnalytics")
I was copying old template files and replacing content, and it was adding them in the csproj like this...
These were not getting picked up with finding the view.
Commenting this out made it work
<ItemGroup>
<Content Remove="EmailTemplates\ConfirmEmail.cshtml" />
<Content Remove="EmailTemplates\ForgotPassword.cshtml" />
</ItemGroup>

How to create a PageStatePersister object that saves view and control state on the Web server

Reading a book I managed to create a class which is than used as a base class to override the Load and Save methods to extract and save view state information to the server. However in the book the author suggests going to the following link and viewing the example to do the following:
Instead of using a page base class, you could use a page adapter. This would modify
the functionality of all pages without having to change their base classes. That's great
if you want to store ViewState on the server for all pages. To find
out how to store ViewState for all pages using the GetStatePersister method of the
PageAdapter class, visit:
All I am trying to do is find a way to save the ViewState without manually changing the base Class on each page.
I get the following error:
[ArgumentNullException: Value cannot be null.
Parameter name: stream]
System.IO.StreamWriter..ctor(Stream stream, Encoding encoding, Int32 bufferSize, Boolean leaveOpen) +10409245
System.IO.StreamWriter..ctor(Stream stream) +30
dev.StreamPageStatePersister.Save() in a:\Project\Application\Web\dev\StreamPageStatePersister.cs:57
System.Web.UI.Page.SavePageStateToPersistenceMedium(Object state) +108
System.Web.UI.Page.SaveAllState() +659
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1225
Here is the link referenced to do this:
http://msdn.microsoft.com/en-us/library/system.web.ui.pagestatepersister.aspx
StreamPageStatePersister.cs Code
namespace dev
{
using System;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
public class StreamPageStatePersister : PageStatePersister
{
public StreamPageStatePersister(Page page)
: base(page)
{
}
public override void Load()
{
Stream stateStream = GetSecureStream();
StreamReader reader = new StreamReader(stateStream);
IStateFormatter formatter = this.StateFormatter;
string fileContents = reader.ReadToEnd();
Pair statePair = (Pair)formatter.Deserialize(fileContents);
ViewState = statePair.First;
ControlState = statePair.Second;
reader.Close();
stateStream.Close();
}
public override void Save()
{
if (ViewState != null || ControlState != null)
{
if (Page.Session != null)
{
Stream stateStream = GetSecureStream();
StreamWriter writer = new StreamWriter(stateStream);
IStateFormatter formatter = this.StateFormatter;
Pair statePair = new Pair(ViewState, ControlState);
// Serialize the statePair object to a string.
string serializedState = formatter.Serialize(statePair);
writer.Write(serializedState);
writer.Close();
stateStream.Close();
}
else
throw new InvalidOperationException("Session needed for StreamPageStatePersister.");
}
}
// Return a secure Stream for your environment.
private Stream GetSecureStream()
{
// You must provide the implementation to build
// a secure Stream for your environment.
return null;
}
}
}
MyPageAdapter.cs Code
namespace dev {
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter
{
public override PageStatePersister GetStatePersister()
{
return new dev.StreamPageStatePersister(Page);
}
} }
Finally in the browser file:
<browsers>
<browser id="NewBrowser" parentID="Mozilla">
<identification>
<userAgent match="Unique User Agent Regular Expression" />
</identification>
<capture>
<userAgent match="NewBrowser (?'version'\d+\.\d+)" />
</capture>
<capabilities>
<capability name="browser" value="My New Browser" />
<capability name="version" value="${version}" />
</capabilities>
</browser>
<browser refID="Mozilla">
<capabilities>
<capability name="xml" value="true" />
</capabilities>
<controlAdapters>
<adapter
controlType="System.Web.UI.Page"
adapterType="dev.MyPageAdapter" />
</controlAdapters>
</browser>
</browsers>
I think you should determine the adapter for the rest of browsers. could u try:
adapterType="Samples.AspNet.CS.MyPageAdapter" />

Unity [Dependency] attribute doesn't resolve

I have the following code, and when I try to run it, I can see that the BrokerProvider is not being resolved. Here is my code:
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection) ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);
new TestBroker().RunTestBroker();
}
class TestBroker
{
private IBrokerProvider brokerProvider;
public void RunTestBroker()
{
List<IPortfolio> portfolios = BrokerProvider.GetPortfolios();
}
[Dependency]
public IBrokerProvider BrokerProvider
{
get { return brokerProvider; }
set { brokerProvider = value; }
}
}
The related config
<unity>
<typeAliases>
<typeAlias alias="string" type="System.String, mscorlib" />
<typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
<typeAlias alias="IBrokerProvider" type="PA.Common.Interfaces.IBrokerProvider, PA.Common" />
<typeAlias alias="PManager" type="PA.BrokerProviders.PManager, PA.BrokerProviders" />
</typeAliases>
<containers>
<container>
<types>
<type type="IBrokerProvider" mapTo="PManager">
<lifetime type="singleton" />
</type>
</types>
</container>
</containers>
</unity>
Another question: Do I need to repeat the same 3 lines of code that I have under main in every other class that I would like to use unity or setting it up once is enough?
That's because are creating TestBroker directly by calling operator new on it:
new TestBroker().RunTestBroker();
In order for unity to resolve your dependencies you need to call the framework like so:
var broker = container.Resolve<TestBroker>();
IUnityContainer is the interface that is going to be doing all the work for you - i.e. resolving types to instances. You only need to create it once and then just pass it around the application where ever you need it.

Resources