C# classes not being called when using MongoDB project - c#

I have an MVC4 website and I am trying to integrate some Mongodb functionality (just experimenting for now). I am using this mongodb project as I am also trying to deploy to Azure, this project provides connection utilities for connecting to the mongodb worker role. I have a MovieController with the following constructor:
public class MovieController : Controller
{
MongoMovieHelper _movies;
public MovieController()
{
_movies = new MongoMovieHelper();
}
}
This in turn calls the class:
public class MongoMovieHelper
{
public MongoCollection<Movie> Collection { get; private set; }
public MongoMovieHelper()
{
MongoServerSettings serverSettings = ConnectionUtilities.GetConnectionSettings();
MongoServer server = MongoServer.Create(serverSettings);
MongoDatabase db = server["movies"];
Collection = db.GetCollection<Movie>(typeof(Movie).Name.ToLower());
}
...
When trying to load any page from the Movie controller I get an internal server error in the Chrome debugger.
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
So I tried debugging in visual studio. The controller constructor gets hit, but any breakpoints within MongoMovieHelper do not, and trying to Step into just hits the controller constructor again. The stack trace displays the following error:
Could not load file or assembly 'MongoDB.Driver, Version=1.4.2.4500,
Culture=neutral, PublicKeyToken=f686731cfb9cc103' or one of its
dependencies. The located assembly's manifest definition does not
match the assembly reference. (Exception from HRESULT: 0x80131040)
Previously I had another class which makes the Mongodb connection so Controller calls MongoMovieHelper which calls MongoDBHelper. In this case, both the controller and MongoMovieHelper were being called, but MongoDBHelper was not, so I believe the problem lies within the mongodb connection.
This is probably some rookie mistake but I just can't figure out what the problem might be, any ideas?

I tried to recreate your problem using the latest version of the official mongodb c# driver but I could not.
I am using the latest official driver available on NuGet:
I changed your code to use non-obsolete methods to get the server object:
public MongoMovieHelper()
{
var client = new MongoClient(MongoUrl.Create("mongodb://localhost:27017"));
var server = client.GetServer();
var db = server["movies"];
Collection = db.GetCollection<Movie>(typeof (Movie).Name.ToLower());
}
So if you are not using the official driver then please use it:
get using the following command:
Install-Package mongocsharpdriver
Then try and change your code to look something like mine and then see if it works.
The error you are getting suggests you are either using an old version of the official driver, or you aren't using the official driver at all.
Note: uninstall the old driver, either through the nuget console (/ui), alternatively remove the binary ref and clean your project ensuring that you don't have any bin dll left hanging around.

Related

Blazor Webassembly, DatabaseCRUD: Internal Server Error 500 with published version

Problem Details
I have a Blazor project with a simple Database-CRUD (create, read, update, delete) example. It works properly when I run it within Visual Studio but if I publish it the program runs into an error.
Project Details
IDE is Visual Studio 2019. Project is Blazor Webassembly. I tried .NET CORE 3.1 and .NET 5.0. Database is SQL Server 2019. IIS for publishing.
Code Details
Database access is working with mapping (Scaffold-DbContext). I use the nuggets “Microsoft.EntityFrameworkCore.Tools” and “Microsoft.EntityFrameworkCore.SqlServer”.
This is the read command:
using var httpResponse = await Http.GetAsync("/api/DataLrs/Index");
This is the read command-snippet I use for more error details:
using var httpResponse = await Http.GetAsync("/api/DataLrs/Index");
if (!httpResponse.IsSuccessStatusCode)
{
// set error message for display, log to console and return
errorMessage = httpResponse.ReasonPhrase;
Console.WriteLine($"There was an error! {errorMessage}");
return;
}
// convert http response data to UsersResponse object
dataLrsList = await httpResponse.Content.ReadFromJsonAsync<DataLrs[]>();
Error Details
When I publish the project with IIS and try to execute the same commands I get the following error in the browser:
Internal Server Error
System.Net.Http.HttpRequestException: net_http_message_not_success_statuscode, 500
Solution Attempts Details
As already mentioned, when I run it in Visual Studio it works without any problems. I already googled and tried several stuff but nothing really works.
How can I get a better error description?
Is anybody familiar with this problem?
I realized many people have the same/similar problem, but I couldn’t find a clear solution
Thanks!
Yes, you are right, I am using EF Core. Sorry! Forgot to mention that important detail.
Database Details
To make it not too complicated I am using a database on my pc and I am also publishing (IIS) on my pc. If all works, I would proceed with a server.
I retrieved my connection string via Visual Studio’s SQLServerObjectExplorer. I use for both modes (debug, publish) the same connection string which is stored in appsettings.json.
This is the connection string:
Data Source=CND823509T\SQLEXPRESS;Initial Catalog=DataComposerWebDBTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False
Method Details
Here are some of my method details, I will just copy the important lines (hope that is enough). I got the structure from a general example I googled. As already mentioned, locally it works.
RazorePage.razor
dataLrsList = await Http.GetFromJsonAsync<DataLrs[]>("/api/DataLrs/Index")
DataLrsAccessLayer.cs
public IEnumerable<DataLrs> GetData()
{
try
{
return _context.DataLrs.ToList();
}
catch (Exception ex)
{
throw;
}
}
DataLrsController.cs
[HttpGet]
[Route("api/DataLrs/Index")]
public IEnumerable<DataLrs> Index()
{
return _dataLrs.GetData();
}
Questions Details
Do you need more details?
What do you mean with localDB stuff?
Thanks!

Visual Studio: Connect MySQL database running on localhost to ASP.NET project

I am currently trying to teach myself ASP.NET, as I will need it on the job soon. For testing purpose, I want to create a simple project with 1 or 2 RazorPages, which derives data from a MySQL database on my localhost. I am using the Visual Studio Community version. I started by creating a new ASP.NET Core Web Application project, then added a "New Connection" (see screenshot)
I also installed the packages "MySqlData", "MySqlData.EntityFrameworkCore" and "MySQLConnector". In appsettings.json, I added
"ConnectionStrings": {
"RazorPagesPlayersContext": "server=localhost;user=root;password=password;database=players;"
}
and in Startup.cs, I configured
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddDbContext<RazorPagesPlayersContext>(options => options.UseSqlite(Configuration.GetConnectionString("RazorPagesPlayersContext")));
}
However, when I to go to the create page and post a new "player" into the database, I am getting error
ArgumentException: Connection string keyword 'server' is not supported
My context file looks like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RazorPagesPlayers.Models;
namespace RazorPagesPlayers.Data
{
public class RazorPagesPlayersContext : DbContext
{
public RazorPagesPlayersContext (DbContextOptions<RazorPagesPlayersContext> options)
: base(options)
{
}
public DbSet<RazorPagesPlayers.Models.Player> Player { get; set; }
}
}
When I check "Connected Services", I can only see this
I can see, that the connection string of this service has nothing to do with the connection string I added in appsettings.json. When I try to change it, it will just switch back. So I am guessing the connection to MySQL failed or am I confusing things here? I am not even sure if I am looking in the right direction, but every hint would be most welcome. Thank you very much in advance
Edit: When I change the Service config in Startup.cs to
services.AddDbContext<RazorPagesPlayersContext>(options => options.UseMySql(Configuration.GetConnectionString("RazorPagesPlayersContext")));
it tells me "DbContextOptionsBuilder" does not contains a defintion for 'UseMySql' and recommends to change it to UseMySQL. This however results in an error:
TypeLoadException: Method 'Create' in type 'MySql.Data.EntityFrameworkCore.Query.Internal.MySQLSqlTranslatingExpressionVisitorFactory' from assembly 'MySql.Data.EntityFrameworkCore, Version=8.0.22.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' does not have an implementation.
is there a point in installing Pomelo?

Get Nuget credentials stored somewhere by Visual Studio in a VSIX project

I'm developing a Visual Studio extension (VSIX project) that needs to manage Nuget packages of a given project.
I'm already using the IVsPackageInstaller service as documented here but this is limited and I need more features (for example get the latest version number of a given package).
I searched but didn't find anything on how to programmatically interact with the Visual Studio Package Manager so I decided to go for the Nuget API directly.
I send HTTP requests to the Nuget API using the WebRequest class (because we can't use HttpClient in a VSIX project) but I'm hitting a problem: the requests are going to a private Nuget feed that needs authentication! (hosted on Azure DevOps)
I used Fiddler to check the HTTP requests sent to our Azure DevOps server. I see a POST request going to https://app.vssps.visualstudio.com/_apis/Token/SessionTokens with a token in response but this is not the Token I'm looking for.
The token passed to the Nuget API is a Basic token that comes from I don't know where. I couldn't find this token anywhere in the HTTP responses I caught.
I can also see that some responses to our Azure DevOps server contain some headers like this (I changed the GUID)
WWW-Authenticate: Bearer authorization_uri=https://login.windows.net/ce372fcc-5e17-490b-ad99-47565dac8a84
I can find this GUID back in the %userprofile%\AppData\Local\.IdentityService\AccountStore.json file, there is definitely something going on here. And the SessionTokens.json file in the same folder looks reeeaaally interesting too but it's encrypted...
I also tried to dig in the Registry to see if I can find interesting information for example at the path specified in Simon's comment but it seems VS2017 doesn't store the token there anymore.
I also loaded the privateregistry.bin file (aka the Visual Studio Settings Store) and searched everywhere but couldn't find anything.
So instead of trying to reverse engineer Visual Studio I wanted to access its Credential Provider directly. I tried to access to several services and classes
var componentModel = await ServiceProvider.GetGlobalServiceAsync(typeof(SComponentModel)) as IComponentModel;
var credentialProvider = componentModel.GetService<IVsCredentialProvider>();
var credentialServiceProvider = componentModel.GetService<ICredentialServiceProvider>();
var defaultCredentialServiceProvider = new DefaultVSCredentialServiceProvider();
But none of them are working (return null or Exception).
I wandered in the NuGet.PackageManagement.VisualStudio project on Github but couldn't find my answer.
There are also many Nuget packages like NuGet.PackageManagement.VisualStudio, Microsoft.VisualStudio.Services.Release.Client, Microsoft.VisualStudio.Services.ExtensionManagement.WebApi, Microsoft.VisualStudio.Services.InteractiveClient just to name a few but honestly I don't know if what I'm looking for is there...
So how to access the Nuget credentials used by Visual Studio?
I take any solution that gives me access to all the reading Nuget features, for example programmatically use the Visual Studio Package Management, or decrypt this SessionTokens.json file or access the Visual Studio Credential Provider.
The less hacky is the answer, the better it is of couse.
At this point you probably already guessed, I don't want to store the username and password somewhere myself. I need to create a user-friendly VS extension, that's why I want to retrieve and use the credentials already saved in Visual Studio by the users.
Thank you so much if you can solve this problem.
NuGet Client SDK
Thanks a lot to Simon who pointed me in the direction of NuGet.Client.
The only documentation from Microsoft is linking a 2016 blog post from Dave Glick but they also give a nice note:
These blog posts were written shortly after the 3.4.3 version of the NuGet client SDK packages were released. Newer versions of the packages may be incompatible with the information in the blog posts.
Alright, then I guess we will do with Dave's blog...
You should install two packages: NuGet.Client and Nuget.Protocol
Then here is the code for example to get the last version of a package:
using NuGet.Configuration;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MyProject
{
public class NugetHelper
{
public async Task<string> GetLatestVersionNumberFromNugetFeedAsync(NugetPackage package)
{
try
{
Logger logger = new Logger(); //Just a class implementing the Nuget.Common.ILogger interface
List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();
providers.AddRange(Repository.Provider.GetCoreV3()); // Add v3 API support
PackageSource packageSource = new PackageSource(package.Source.ToString());
SourceRepository sourceRepository = new SourceRepository(packageSource, providers);
PackageMetadataResource packageMetadataResource = await sourceRepository.GetResourceAsync<PackageMetadataResource>();
var searchMetadata = await packageMetadataResource.GetMetadataAsync(package.Name, false, false, new SourceCacheContext(), logger, new CancellationToken());
var versionNumber = searchMetadata.FirstOrDefault().Identity.Version.OriginalVersion;
return versionNumber;
}
catch (Exception ex)
{
return null;
}
}
}
public class NugetPackage
{
public string Name { get; set; }
public string Version { get; set; }
public string MinimumVersion { get; set; }
public Uri Source { get; set; }
}
}
Physical Token Storage Place
I tried to reverse engineer where Visual Studio was storing the token used in HTTP requests to the Nuget API.
I exported to text files all the different hives of the Registry including the Visual Studio Settings Store (privateregistry.bin).
Then added a brand new Nuget feed in Visual Studio, got the login popup as expected so I logged in.
Finally I exported all the hives again to text files and compared them all with the files before authentication.
I found nothing interesting in the VS Settings Store.
The only interesting changes were
[HKEY_CURRENT_USER\Software\Microsoft\VSCommon\ConnectedUser\IdeUserV2]
#="0746fb8e-4bc2-4ee5-b804-0084af725deb"
"AccountsRoaming_LastAccountsSettingVersion"=dword:0000025b
[HKEY_CURRENT_USER\Software\Microsoft\VsHub\ServiceModules\Settings\PerHubName\vshub\ConnectedUser\IdeUserV2\Cache]
"LastProfileVersion"=dword:10b8260a
and
[HKEY_USERS\S-1-5-21-1787888774-1556370510-3519259403-1001\Software\Microsoft\VSCommon\Keychain]
"TokenStorageNameSpace"="VisualStudio"
[HKEY_USERS\S-1-5-21-1787888774-1556370510-3519259403-1001\Software\Microsoft\VsHub\ServiceModules\Settings\PerHubName\vshub\ConnectedUser\IdeUserV2\Cache]
"LastProfileVersion"=dword:10b8260a
Maybe somewhere, there is the key to these encrypted SessionTokens.json and IdentityServiceAdalCache.cache files but having the data stored in hexadecimal makes things even harder.
I've to give up on this, almost no chance I could reverse engineer the authentication system.
Visual Studio credentials provider
The NuGet Client SDK solves my issue but doesn't actually answer to this SO question.
As I said, I tried to call
var componentModel = await ServiceProvider.GetGlobalServiceAsync(typeof(SComponentModel)) as IComponentModel;
componentModel.GetService<ICredentialServiceProvider>()
But this didn't work, so if anybody knows how to access the Visual Studio credentials provider, I would be really glad to know the answer.

Item added to DbContext twice

I am very new to SP.NET MVC, so excuse me for missing basic stuff.
I have created a website working with a database (Microsoft SQL Server) and I'm using Entity Framework package to manage it.
I have a DatabaseManager class as following:
Public class DatabaseManager : DbContext
{
Public DbSet<Connection> Connections { get; set; }
.
.
.
}
My application listens for syslog connections and then updates the Connections member accordingly:
Db.connections.Add(new Connection(SourceIp, DestinationIp))
db.SaveChanges();
Anyway, however weird it may seem, when I add a connection to the DbContext two connection are added (both identical) instead of one.
What might be my problem?
If you have registered event listener twice or included the registering file (may be JS file) twice, this issue would come. You can any time check at Firebug with list of events attached..

Embedded RavenDB in asp.net MVC website does not initialize

Why can't I make an embedded RavenDB work in a fresh asp.net MVC website?
I have successfully tried and tested the following code in a simple .net console application. It works just fine, until I try and use it in an MVC website.
It doesn't throw any error, it just hangs after attempting to Initialize()
In my bug-finding process, I installed a RavenDB server on localhost, which I can connect to in my MVC application - that is not a problem. But the initialize error was there before I installed the localhost RavenDB as well as after.
I hope you can help sort this out!
public static class Store {
private static IDocumentStore store = createStore();
private static EmbeddableDocumentStore createStore() {
var returnStore = new EmbeddableDocumentStore();
returnStore.DataDirectory = #"./PersistedData";
returnStore.Initialize(); // It never gets past this in any MVC website
return returnStore;
}
public static myDocument Read(string key) {
using (var session = store.OpenSession()) {
var anEntity = session.Query<myDocument>().Where(item => item.key == key).Single();
return anEntity;
}
}
public static void Write(myDocument d) {
using (var session = store.OpenSession()) {
session.Store(d);
session.SaveChanges();
}
}
}
public class myDocument {
public string key { get; set; }
public string description { get; set; }
}
UPDATE
The following errors are logged and show up in the Event Viewer:
INFORMATION: Raven (11096) 1-RT4um-C:\Users\***\RavenEmbed\./PersistedData\Data:
The database engine attached a database (1, C:\Users\***\RavenEmbed\PersistedData\Data).
(Time=0 seconds)
ERROR: Windows cannot open the 64-bit extensible counter DLL ASP.NET_64_2.0.50727 in a
32-bit environment. Contact the file vendor to obtain a 32-bit version. Alternatively if
you are running a 64-bit native environment, you can open the 64-bit extensible counter
DLL by using the 64-bit version of Performance Monitor. To use this tool, open the
Windows folder, open the System32 folder, and then start Perfmon.exe.
ERROR: Disabled performance counter data collection for this session from the
"ASP.NET_64_2.0.50727" service because the performance counter library for that service
has generated one or more errors. The errors that forced this action have been written
to the application event log.
ERROR: The Open Procedure for service "BITS" in DLL "C:\Windows\System32\bitsperf.dll"
failed. Performance data for this service will not be available. The first four bytes
(DWORD) of the Data section contains the error code.
ERROR: The Open Procedure for service "Lsa" in DLL "C:\Windows\System32\Secur32.dll"
failed. Performance data for this service will not be available. The first four bytes
(DWORD) of the Data section contains the error code.
ERROR: The Open Procedure for service "MSDTC" in DLL "C:\Windows\system32\msdtcuiu.DLL"
failed. Performance data for this service will not be available. The first four bytes
(DWORD) of the Data section contains the error code.
ERROR: The configuration information of the performance library "perf-MSSQL$SQLEXPRESS-
sqlctr11.1.3000.0.dll" for the "MSSQL$SQLEXPRESS" service does not match the trusted
performance library information stored in the registry. The functions in this library
will not be treated as trusted.
UPDATE 2
I can download an MVC 3 project from this link, which works. But I still can't the MVC 4 embedded RavenDB to work.
http://archive.msdn.microsoft.com/mag201111NoSQL/Release/ProjectReleases.aspx?ReleaseId=5778

Categories