Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von Davaaron
Thema: SSMS: Verbindung zu SQL-Server aus Docker-Container herstellen
Am im Forum: Datentechnologien

Ok, ich probiere es mal. Ich hoffe mal, dass die anderen Services dann dennoch auf die Datenbank zugreifen können :D

Danke schon mal.


Edit: Super, hat einwandfrei funktioniert! Jetzt kann ich mich auch über SSMS einloggen und die Applikation läuft dennoch ganz normal, macht ja aber auch Sinn, weil die 31000 nur von Docker aus "exposed" wird und intern immer noch die 1433 genutzt wird.

Thema: SSMS: Verbindung zu SQL-Server aus Docker-Container herstellen
Am im Forum: Datentechnologien

verwendetes Datenbanksystem: SQL Server

Hallo,

ich habe eine Entwicklungsumgebung vorliegen, bei der ein Docker-Image erstellt wird und in einem Docker-Container läuft. Das Image ist ein mssql-Image und dort wird eine DB inklusive Seeding und Migration erstellt.
Nun würde ich gerne von meinem Host über SQL Server Management Studio (SSMS) auf diese Datenbank zugreifen. Der ConnectionString für die DB beinhaltet

Data Source=localhost
sowie eine User ID und ein Passwort.
Versuche ich nun über SSMS diese Credentials (SQL Authentifizierung) einzugeben und trage als Servername "localhost" ein, bekomme ich einen Fehler:
"Fehler bei der Anmeldung für den Benutzer "sa" (Microsoft SQL Server, Fehler: 18456)"

Verwende ich statt der SQL Auth Methode die Windows Auth Methode, dann komme ich auf meine localhost Datenbank, allerdings ist dies nicht die DB aus dem Docker.

Hat jemand eine Idee, wie ich auf die Docker DB zugreifen kann? Leider kann ich an der docker-Datei nichts ändern.

Thema: MSBuild: XDT Transformation beim Builden
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Wie fast immer: Ich schreibe einen Post und danach fällt mir die Lösung ein.. :D

Der Name des Target-Elements muss auf "AfterBuild" gestellt werden und app.config muss App.config heißen. Das wars auch schon.

Thema: MSBuild: XDT Transformation beim Builden
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hi,

mein Ziel ist es, meine App.*.config Dateien bei jedem Build-Durchlauf zu transformieren, so dass immer die korrekte App.config bereitgestellt wird.
Dazu habe ich in meiner *.csproj folgendes hinzugefügt:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="CoreCompile" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
    <!-- Force build process to use the transformed configuration file from now on. -->
    <ItemGroup>
      <AppConfigWithTargetPath Remove="app.config" />
      <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
        <TargetPath>$(TargetFileName).config</TargetPath>
      </AppConfigWithTargetPath>
    </ItemGroup>
  </Target>

Dies funktioniert, wenn der obj/Debug bzw obj/Release Ordner vorhanden sind und die *.exe ebenfalls. Lösche ich allerdings den obj-Ordner, dann funktioniert das Builden nicht mehr. Fehlermeldung:
  Microsoft.Common.CurrentVersion.targets(4187, 5): [MSB3030] Datei "obj\Debug\MeinProjekt.exe" konnte nicht kopiert werden, da die Datei nicht gefunden wurde.

Wieso wird diese Fehlermeldung geworfen? Ich versuche doch gar nicht auf die *.exe zuzugreifen. Vielleicht wegen der Variable $(TargetFilename)?

Thema: Swagger UI: Mit Basic anmelden, aber JWT für Autorisierung nutzen
Am im Forum: Web-Technologien

Ich habe da ein eigenes Konstrukt, benutze kein OpenId oder OAuth2.
Mittlerweile habe ich es hinbekommen, dass mein Token in jedem Request mitgesendet wird und somit kann ich mich authorisieren.
Den JWT Token nutze ich im Header um den User zu authorisieren, der Refresh-Token ist ein Eigenkonstrukt.

Zitat
Was meinst Du "in Swagger" ? Swagger ist ja nur ein "Protokoll", das hat ja keinen eigenen Controller.
Stimmt, ich meinte damit den Endpunkt zum Einloggen, den ich in Swagger UI sehe. Dieser Endpunkt hat ja einen Controller.
Zitat
Fürs Protokoll: Du verwendest SwashBuckle, richtig?
Richtig.


Noch eine andere Frage (oder dazu einen eigenen Thread aufmachen?).
Ich würde gerne, bevor die index.html von Swagger UI aufgerufen wird, eine eigene HTML Seite anzeigen. Dies habe ich auch hinbekommen, indem ich den IndexStream überschrieben habe:


 app.UseSwaggerUI(c =>
            {
              
                c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("My.Custom.Namespace.Resources.firstPage.html");
            });

Nun würde ich gerne zur originalen Swagger UI Index.html navigieren. Dazu habe ich mir von Github das originale index.html heruntergeladen.
Das Problem: Ich weiß nicht, wie ich dahin navigieren soll. Beim Starten der WebAPI komme ich direkt auf "index.html", d.h. meine firstPage.html dient logischerweise als index.html. Die originale index.html von Swagger UI wird nicht migeladen.
Hat das schon mal jemand gemacht?

Thema: Swagger UI: Mit Basic anmelden, aber JWT für Autorisierung nutzen
Am im Forum: Web-Technologien

Hi,

für meine Asp.Net Core Web Api habe ich einige Controller, die mit dem AuthorizeAttribute versehen sind. Für die Autorisierung benutze ich JWT Tokens. Nun will ich Swagger UI nutzen, um die WebAPI zu dokumentieren und zu testen.
Da nicht jeder die API nutzen können soll, will ich diese absichern, allerdings nicht mit einem JWT Token, sondern der Benutzer soll sich normal per Basic Auth autorisieren. Dafür habe ich auch keinen AuthController, der den JWT inklusive Refresh-Token zurückgibt.
Doch wie erreiche ich das?
In meiner Startup.cs habe ich folgenden Code:

  services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web API", Version = "v1" });

                // add JWT Authentication
                var securityScheme = new OpenApiSecurityScheme
                {
                    Name = "JWT Authentication",
                    Description = "Enter JWT Bearer token **_only_**",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.Http,
                    Scheme = "bearer", // must be lower case
                    BearerFormat = "JWT",
                    Reference = new OpenApiReference
                    {
                        Id = JwtBearerDefaults.AuthenticationScheme,
                        Type = ReferenceType.SecurityScheme
                    }
                };
                c.AddSecurityDefinition(securityScheme.Reference.Id, securityScheme);
                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {securityScheme, new string[] { }}
                });

                // add Basic Authentication
                var basicSecurityScheme = new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.Http,
                    Scheme = "basic",
                    Reference = new OpenApiReference { Id = "BasicAuth", Type = ReferenceType.SecurityScheme }
                };
                c.AddSecurityDefinition(basicSecurityScheme.Reference.Id, basicSecurityScheme);
                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {basicSecurityScheme, new string[] { }}
                });

                
            });

Zum Testen habe ich hier zwei Autorisierungs-Methoden: JWT und Basic.
Um meinen JWT Token zu bekommen, nutze ich meinen AuthController in Swagger. Wenn ich mich darüber anmelde, wird der Token leider nicht im Header mitgegeben. Bei Basic Auth wird der Basic string allerdings mitgegeben.
Mit der Dokumentation von Swagger UI kann ich leider überhaupt nichts anfangen.

Zusätzlich habe ich noch eine andere Frage:
All meine Web API Endpunkte sind nun mit einem Schloss versehen, obwohl nicht alle Endpunkte mit dem AuthorizeAttribute versehen sind. Wieso? Und wie kann ich nur jene, die auch eine Autorisierung benötigen, mit einem Schloss versehen?

Thema: Wie kann ich bei bei OData (Connected Services) in VS bessere Exceptions anzeigen?
Am im Forum: Netzwerktechnologien

Habe über "Webverweis hinzufügen" die Dienst aus BC übernehmen können. Dies hat mir einige WSDL Dateien generier, allerdings kann Visual Studio die Klassen dafür nicht finden.
Bspw. habe ich eine "MitarbeiterPlan.wsdl" und der Webverweisname ist "SoapService".
Laut Blog-Post sollte ich nun den Service mit

SoapService.MitarbeiterPlan plan = new SoapService.MitarbeiterPlan() 

instanziieren und verwenden können.

Nur Probleme.. ;(

Thema: Wie kann ich bei bei OData (Connected Services) in VS bessere Exceptions anzeigen?
Am im Forum: Netzwerktechnologien

Zitat
Warum magst Du darauf setzen?
Mögen ganz und gar nicht. Ich mag SOAP nicht, erinnert mich immer an WCF und das mochte ich auch nicht.

Aber ich denke ich muss, weil ich eine Codeunit habe, die ich gerne per API anstoßen will und das leider nur mit SOAP funktioniert laut Microsoft:

Microsoft Web-Services

Wüsste sonst nicht, wie ich das ermöglichen könnte.

Thema: Wie kann ich bei bei OData (Connected Services) in VS bessere Exceptions anzeigen?
Am im Forum: Netzwerktechnologien

Weiß jemand, ob man SOAP statt ODataV4 verwenden kann und ob es dafür schon Libraries gibt?

Thema: Wie kann ich bei bei OData (Connected Services) in VS bessere Exceptions anzeigen?
Am im Forum: Netzwerktechnologien

Zitat
Aber es ist halt auch nur ein Code Generator, der nicht zwangsläufig alle Anforderung abdecken kann, die Du haben willst - und er ist veraltet.

Also ich benutze hierfür die "OData Connected Service" Erweiterung, die, glaube ich, nicht veraltet ist, denn sie erstellt OData V4 Services, die wiederum Klassen aus dem "OData Client" Projekt verwenden. Beispielsweise kommt der automatisch erstellte Datenkontext (DataServiceContext) aus Namespace "Microsoft.OData.Client".
Zitat
Gibt es eine Möglichkeit, auch in Visual Studio die genauen Exceptions anzuzeigen?
Zitat
Nein, denn Visual Studio ist prinzipiell nur eine Entwicklungsumgebung. Wenn Dir der OData Client das nicht aufsammeln, dann bekommst Du natürlich auch nichts.
Die Frage habe ich missverständlich gestellt. Damit meinte ich eher, ob ich es mithilfe der Connected Services (OData) so gut hinbekommen kann wie der Web Debugger von Fiddler.

@Papst, @Abt
Das würde wahrscheinlich mit OData Lib gehen (habe ich gerade eben durch Abts Link gefunden), aber das ist mir zu viel Aufwand für das aktuelle Projekt. Ich bleibe bei Fiddler (wieso Dinge neu erfinden). Wäre aber für die Zukunft sicherlich ein Gedanke wert, alleine schon des Loggings wegen.

Thema: Wie kann ich bei bei OData (Connected Services) in VS bessere Exceptions anzeigen?
Am im Forum: Netzwerktechnologien

Von der Struktur erinnert mich die OData Client API etwas an Entity Framework: Man hat einen Context mit allen Endpunkten als Properties (z.B. new MyContext().Persons.ToList()) und man kann Queries erstellen. Allerdings finde ich keinen Weg, direkt an den Http Client zu kommen.
Man kann an ein paar Events hängen bzw Actions/Funcs mitgeben, aber auch da sehe ich aktuell keine Chance. Ein Event "ReceivingResponse" scheint zunächst mal vielversprechend, aber in der HttpResponseMessage Klasse sehe ich den Body nicht bzw sehe auch da nur "400 - Bad Request".
Wahrscheinlich müsste ich mir das alles selbst aus dem Stream ziehen und dekodieren. Ich werde voerst bei Web Debugger bleiben.

Thema: Wie kann ich bei bei OData (Connected Services) in VS bessere Exceptions anzeigen?
Am im Forum: Netzwerktechnologien

Hi,

für meine Business Central API habe ich mir Connected Services (ist eine Erweiterung von Visual Studio, früher ging das mit "Add service reference") erstellt. Die Erweiterung erstellt mir Proxies aus der angegebenen $metadata-URL, die ich dann ganz einfach im Code verwenden kann.
Beim Testen dieser Services ist mir aufgefallen, dass ich manchmal ein "Bad Request" - 400 zurückbekomme, ohne Inhalt oder einer Bemerkung, was schief gelaufen ist. Zum Glück habe ich den Web Debugger von Telerik gefunden, der mir das Mitschneiden des Network traffics erlaubt und glücklicherweise auch die SSL (wohl eher TLS) verschlüsselten Requests and Reponses anzeigt. In der Reponse sehe ich dann, was genau schief gelaufen ist. Allerdings sehe ich die konkrete Fehlermeldung nicht beim Debuggen in Visual Studio.

Gibt es eine Möglichkeit, auch in Visual Studio die genauen Exceptions anzuzeigen?

Thema: Wie können Library und App jeweils auf das gleiche ResourceDictionary zugreifen?
Am im Forum: GUI: WPF und XAML

Ok, das war einfach...
aus irgendeinem Grund war für Icons.xaml im "Benutzerdefiniertes Tool"-Eintrag "MSBuild:Compile" eingetragen. Diesen Eintrag habe ich entfernt und habe das Bild magnifier.png auf Resource gesetzt und "immer kopieren".

Thema: Wie können Library und App jeweils auf das gleiche ResourceDictionary zugreifen?
Am im Forum: GUI: WPF und XAML

Hi,

damit ich künftig nicht mehr immer wieder von 0 anfangen muss, verlagere ich gerade ein paar UserControls in eine Library aus. Meine Vorstellung ist es, dass die Library schon alle ResourceDictionaries beinhaltet, die in dieser Library gebraucht werden wie Icons, Styles für Buttons, Texts, etc. Die Styles sollen später zu einem DefaultTheme.xaml zusammengefasst werden mithilfe von MergedResourceDictionary.
Die Library wird in meine App eingebunden und dort sollen die Styles geladen werden in der App.xaml.

Dabei hätte ich gerne volle Design-Time Unterstützung für die Library und für die App, d.h. der Designer sollte alle Styles und Icons anzeigen. Hier soll es aber zunächst mal nur um die Icons gehen. Im Anhang seht ihr übrigens die Projektstruktur.

Die Icons.xaml ist minimalistisch und sieht so aus:


<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:Davaaron.WPFManager.Resources">
    <BitmapImage x:Key="SearchIcon" UriSource="/Davaaron.WPF.Controls;component/Resources/Images/magnifier.png" />

</ResourceDictionary>

Als Beispiel ziehe ich mal meine SideMenuView heran:
<UserControl x:Class="Davaaron.WPF.Controls.Views.SideMenuView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Davaaron.WPF.Controls.Views"
             mc:Ignorable="d" 
             xmlns:vm="clr-namespace:Davaaron.WPF.Controls.ViewModels"
             d:DesignHeight="200" d:DesignWidth="150"
             d:DataContext="{d:DesignInstance vm:SideMenuViewModel, IsDesignTimeCreatable=True}">

    <!--<UserControl.Resources>
        <ResourceDictionary Source="../Resources/Dictionaries/Icons.xaml"/>
    </UserControl.Resources>-->
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="25"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBox VerticalContentAlignment="Center">Hello, dude</TextBox>
            <Button Grid.Column="1" Command="{Binding }">
                <!--<Image Source="{StaticResource SearchIcon}"></Image>-->
                <Image Source="../Resources/Images/magnifier.png"></Image>
            </Button>

        </Grid>
        <TreeView Grid.Row="1" ItemsSource="{Binding Items}">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type vm:SideMenuItem}" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding DisplayName}"></TextBlock>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>
</UserControl>

Ich habe mehrere Wege ohne Erfolg probiert:


Fall 1 (auskommentierte Zeilen in SideMenuView.xaml):
Resource-Dictionary wird in dem UserControl innerhalb der Library eingebunden und im Image-Control wird die StaticResource angegeben. Der Designer zeigt das Icon nicht an, obwohl der Code fehlerfrei ist. IntelliSense zeigt mir sogar "SearchIcon" an. Starte ich die Applikation, fehlt allerdings das Icon.

Fall 2 (so wie oben gezeigt):
Das Icon wird direkt an die Source des Images gebunden (relativer Pfad). Der Designer zeigt das Icon an, aber auch beim Start der Applikation fehlt dieses. Diese Implementierung bevorzuge ich nicht, sondern war eher als "Proof of concept" gedacht.

Wenn ich in meiner App.xaml das ResourceDictionary aus WPF.Controls einbinde, bekomme ich den Fehler, dass das ResourceDictionary bereits eingebunden wurde, egal ob ich Fall 1 oder 2 verwende.


Nun meine Frage:
Wie realisiere ich es, dass ich in der Library und in der App jeweils auf die gleiche ResourceDictionary zugreifen kann? Viele Bibliotheken wie Metro bspw verwenden intern ja die selben Styles, die der Benutzer später in seiner App.xaml angibt.

Thema: Wieso validiert eine RegularExpression Annotation immer zu false?
Am im Forum: Grundlagen von C#

Mit ScalePrecision habe ich es nicht hinbekommen. Wenn ich es richtig verstehe, geht das aber auch schlecht. Allerdings konnte ich dort mein Regex einfügen und die Validierung funktioniert. Natürlich zuerst in ein string umwandeln.

Bei der Microsoft Annotation Lösung habe ich meinen double gegen ein string getauscht und es hat dennoch nicht funktioniert.

Thema: Wieso validiert eine RegularExpression Annotation immer zu false?
Am im Forum: Grundlagen von C#

Stimmt, stimmt. Vieles wird über Nuget Pakete importiert. Trotzdem wollte ich es mal mit einer Microsoft Lösung versuchen. Beim Loggen benutze ich auch immer Serilog oder NLog, wobei es eine Microsoft Lösung gibt. Aber ja, ich gucke mir gerade FluentValidation an, das wird ja hoch gelobt.

Die Erklärung mit dem Double vs String macht Sinn. Dachte der validiert auch gegen Doubles, aber das erklärt, warum es nicht funktioniert.

Thema: Wieso validiert eine RegularExpression Annotation immer zu false?
Am im Forum: Grundlagen von C#

Eigentlich ist es eine .NET 4.7 Konsolenapplikation. ValidationContext habe ich als "Built-In" Klasse gefunden (kommt ja von System.ComponentModel.DataAnnotations). Mich wundert es nur, dass die Built-In Validierung nicht wirklich zu funktionieren scheint. Andere Annotations habe ich noch nicht ausprobiert.

Die Annotation gefallen mir besser als alles "fluent" zu schreiben. Nuget Pakete wollte ich eigentlich vermeiden. Wollte mal sehen, was Microsoft so zu bieten hat und wie es "von Haus aus" funktioniert.

Thema: Wieso validiert eine RegularExpression Annotation immer zu false?
Am im Forum: Grundlagen von C#

Hi,

ich würde gerne ein paar Constraints für meine Domain-Models angeben per Annotation.
Für eine double-Property habe ich die Voraussetzung, die Zahl nach dem Schema "####.##" aufgebaut ist, also maximal 4 Dezimalstellen und 2 Nachkommastellen hat.
Als valide würde ich beispielsweise
255.5
255.55
.55
2.55
2.5
255.
bezeichnen.

Meine Annotation sieht so aus:


[RegularExpression(@"\d{1,4}(\.\d{0,2})?", ErrorMessage = "Invalid property (4/2)")]
public double Property{ get; set; }

Die Methode zum Validieren sieht wie folgt aus (alle Models bekommen per Vererbung die Methode zur Verfügung gestellt, daher ist "this" das aktuelle konkrete Objekt)


public (bool isValid, List<ValidationResult> validationResults) Validate()
{
    var context = new ValidationContext(this, serviceProvider: null, items: null);
    var validationResults = new List<ValidationResult>();

    bool isValid = Validator.TryValidateObject(this, context, validationResults, true);
    return (isValid, validationResults);
}

Wenn ich nun Validate aufrufe, bekomme ich immer false.


var obj = new MyObject(); //erbt die Methode Validate()
obj.Property = 255.55;
var val = obj.Validate();
Console.WriteLine(val.isValid); // = false

Wieso?

Wenn ich das ganze manuell mache mit Regex, dann funktioniert es einwandfrei, hier mal ein paar Beispiele:


var regexp3 = @"\d{1,4}(\.\d{0,2})?";
            Regex re3 = new Regex(regexp3);
            var m7 = re3.IsMatch("-120");
            var m8 = re3.IsMatch("200.55");
            var m9 = re3.IsMatch("200.5");
            var m10 = re3.IsMatch("200.");
            var m11 = re3.IsMatch(".33");
            var m12 = re3.IsMatch("100");

Thema: E-Mails synchronisieren nicht zwischen Outlook auf Win10 PC und Android Handy.
Am im Forum: Office-Technologien

Aso, danke für die Erklärung.

Die Erweiterung gucke ich mir mal an.

Thema: E-Mails synchronisieren nicht zwischen Outlook auf Win10 PC und Android Handy.
Am im Forum: Office-Technologien

Okay, verstanden.
Bedeutet das also, dass ich ohne ein Exchange-Konto keine richtige Synchronisation hinbekomme?

Zitat
Dass die Mail niemals in Outlook ankam wird vermutlich daran liegen, dass Du nach dem Abrufen der Mails diese vom Server löscht (über IMAP, teil der Settings).

Das hieße ja, ich kann mir die Arbeit sparen, andere Clients als Outlook zu testen, richtig?

Thema: E-Mails synchronisieren nicht zwischen Outlook auf Win10 PC und Android Handy.
Am im Forum: Office-Technologien

Hi,

Outlook ist auf meinem PC (Win10) und meinem Handy (Android) installiert. Das Problem ist, dass ich nicht alle E-Mails auf dem Handy als auch auf dem PC anschauen kann.
Beispielsweise habe ich heute zwei E-Mails bekommen, die ich direkt auf dem Handy gelesen habe. Antworten wollte ich über den PC, aber da kam die E-Mail niemals an.

Die verwendete E-Mail Adresse ist von web.de und die Kontoeinstellungen beider Outlook-Accounts läuft mit IMAP (Web.de-Server: imap.web.de mit Port 993).

Hat einer von euch eine Idee, woran es liegen könnte, dass die E-Mails nicht synchronisiert werden?

Thema: Wie auf Testing-Methoden-Ebene angeben, dass ich Seeding brauche (oder nicht)?
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hi,

im Wesentlichen geht es darum, dass ich in meinem Projekt ein Datenseeding auf Methodenebene anstrebe. Aktuell verwende ich XUnit zum Testen meiner Services (MVC Service/Repo, die EF Core's DbContext verwenden) und das funktioniert auch ganz gut. Ein klassischer Aufbau eines solchen Tests



public class SpecialServiceTests: BaseServiceTests
{

    public ServiceTests()
    {
         _serviceUnderTest = Resolve<SpecialService>();
    }

    [Fact]
    public async Task CreateMultipleObjects_Retrieve_ShouldNotBeNull()
    {
          //omitted for brevity
    }

    [Fact]
    public async Task DeleteSingleObject_Retrieve_ShouldBeNull()
    {
          //omitted for brevity
    }
}


Jede Testklasse erbt von BaseServiceTest, in dessen Konstruktur die Erstellung des DbContexts und das Datenseeding stattfindet, d.h. jede Methode hat ihre eigene DbContext-Instanz (InMemory) und sind somit voneinander isoliert.
Nun ist es so, dass ich nicht für jede Methode das Seeding benötige, bspw. für die Methode "CreateMultipleObjects". Dies will ich ändern, und zwar möglichst elegant.

Nach langer Überlegung komme ich zu folgendem Schluss: Ich kann nicht explizit sagen, dass für eine bestimmte Methode das Seeding gemacht werden soll. Daher müsste ich generell hingehen und sagen, dass das Seeding überhaupt nicht stattfindet im Konstruktur, sondern am Anfang einer jeden Methode, die das Seeding benötigt.
Also z.B.



    [Fact]
    public async Task CreateMultipleObjects_Retrieve_ShouldNotBeNull()
    {
          //does not need seeding, do your stuff
          Enumerable.Range(1, 10).ForEach(x => ....);
    }

    [Fact]
    public async Task DeleteSingleObject_Retrieve_ShouldBeNull()
    {
          //needs seeding
          SeedData();
          
          //Now do your stuff
    }


Diese Lösung gefällt mir nicht, vor allem weil es bedeutend mehr Testfälle gibt, in denen ich das Seeding brauche. Meine liebste Lösung wäre, einfach mithilfe eines Attributs an einer Methode zu sagen, dass es kein Seeding braucht.

Dafür bräuchte ich aber mehr Kontrolle über das Test-Framework. Soweit ich weiß, weiß XUnit im Konstruktur der Testklasse noch gar nicht, welche Methode ausgeführt wird und eine solche Flexibilität wie ich sie gerne hätte, habe ich auf der XUnit Seite nicht finden können.

Kann mir jemand weiterhelfen? Ich wäre auch bereit, auf ein anderes Test-Framework umzusteigen.

Hinweis:
Das Seeding findet klassisch in C# statt. Später will ich noch die Möglichkeit, das Seeding per ".json" oder ".xml" anzugeben, damit man nicht jedes Mal den Code anpassen muss, wenn sich etwas ändert.


Edit: So etwas in der Art wäre toll


    [Fact]
    [Seed(typeof(MySpecialDbContext), typeof(MySpecialEntity), typeof(MyDependentEntity))]
    //oder einfach [Seed]
    public async Task DeleteSingleObject_Retrieve_ShouldBeNull()
    {
          //Seeding happens by attribute
          
          //Now do your stuff
    }


Damit könnte ich angeben, welcher DbContext mit welchen Entities geseedet werden soll. Dafür bräuchte ich logischen Code, der im Attribut selbst ausgeführt wird. Oder ich gebe einfach ein Flag mit, ob geseedet wird oder nicht.

Thema: Kann man DbSets aus unterschiedlichen DbContexts "verbinden"?
Am im Forum: Datentechnologien

Die Architektur ist etwas das Problem. Aber dann weiß ich ja, wo ich anfangen muss.

Danke für eure Hilfe. Ohne euch hätte ich wahrscheinlich noch ewig probiert, die zwei DbSets irgendwie zu verbinden.

Thema: Kann man DbSets aus unterschiedlichen DbContexts "verbinden"?
Am im Forum: Datentechnologien

Der DbContext wird mittlerweile zu groß. Viele Bereiche benötigen jedoch nur immer nur einen Teil des DbContexts, daher die Überlegung mit dem Aufteilen.

Thema: Kann man DbSets aus unterschiedlichen DbContexts "verbinden"?
Am im Forum: Datentechnologien

Puh, schade.
Ich hatte die Idee, meine Anwendung in kleine Module zu unterteilen und pro Modul sollte es ein DbContext geben. Natürlich gibt es da hin und wieder Überschneidungen, 100%ige Bounded Context sind leider nicht möglich.

Ich probiere mal, inwieweit ich den DbInterceptor ausreizen kann. Meine App unterstützt Dependency Injection, vielleicht kann ich einen eigenen DbInterceptor schreiben, der auf die besonderen Entitäten bzw. Properties achtet und aus dem richtigen Kontext liest und füllt.

Thema: Kann man DbSets aus unterschiedlichen DbContexts "verbinden"?
Am im Forum: Datentechnologien

[Verwendet wird Sqlite In-Memory, es soll aber für SqlServer, Sqlite und InMemory funktionieren]


Hi,

ich stehe gerade vor dem Problem, zwei Db-Kontexte zu verbinden. Genauer es geht darum, dass es in einem DbContext "PersonDbContext" ein DbSet<Person> gibt, dessen Klasse "Person" Properties besitzt, die in dem anderen DbContext "DocumentDbContext" als DbSet definiert sind.
Angenommen eine Person kann sich eine Medienlizenz auf einer Plattform kaufen. Die Person ist in PersonDbContext definiert und die "MediaLicense" in "DocumentDbContext". Ziel ist es, eine Person inklusive einer "MediaLicense" zu laden, wobei das "MediaLicense-Objekt" als Property an der Person hängt. Also:


var person = personDbContext.Persons.Include(x => x.License).FirstOrDefault();
Assert.True(person.License!=null);


Jedoch bekomme ich einen Fehler "FOREIGN KEY constraint failed" wenn ich der Person eine LicenseId hinzufüge..

So seede ich die Daten: zuerst SeedDocuments, dann SeedPersons (DocumentService benutzt DocumentDbContext, PersonService benutzt PersonDbContext):


 private static void SeedPersons(PersonService persService, DocumentService docService)
        {
            var persons = persService.GetPersons();
            if (!persons.Any())
            {
                var license = docService.GetMediaLicenses().FirstOrDefault();
                var docs = docService.GetDocuments();
                persService.Insert(new PersonModule.Entites.Person()
                {
                    Id = Guid.NewGuid(),
                    FirstName = "A",
                    Lastname = "B",
                    //LicenseId = license.Id
                });
            }
        }

        private static void SeedDocuments(DocumentService docService)
        {
            var licenses = docService.GetMediaLicenses();
            if (!licenses.Any())
            {

                docService.Insert(new DocumentModule.Entities.MediaLicense()
                {
                    Id = Guid.NewGuid(),
                    Code = "Code1"
                });

                docService.Insert(new DocumentModule.Entities.MediaLicense()
                {
                    Id = Guid.NewGuid(),
                    Code = "Code2"
                });

                docService.Insert(new DocumentModule.Entities.MediaLicense()
                {
                    Id = Guid.NewGuid(),
                    Code = "Code3"
                });
            }
        }

Wenn ich die auskommentierte Zeile "//LicenseId = license.Id" einfüge, dann kommt die Fehlermeldung. Wenn ich statt einer Id direkt das Objekt setze, also statt "LicenseId = license.Id" setze ich "License = license", dann wird ein Eintrag hinzugefügt und das Speichern & Laden funktioniert. Allerdings gibt es Situationen, in denen nicht das ganze Objekt vorhanden ist, sondern nur die Id, weshalb es gut wäre, wenn es auch funktionieren würde, wenn ich nur die LicenseId setze. Hat jemand eine Idee, wie ich zum Ziel komme? Muss ich einen eigenen DbInterceptor schreiben oder den DbContext nur richtig konfigurieren? Wenn ja, hat jemand eine Idee Ahnung wie?

Klassendefinitionen:

Klasse Person:


 public class Person
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string Lastname { get; set; }
        public ICollection<Document> Documents { get; set; }

        public Guid? LicenseId { get; set; }
        public MediaLicense License { get; set; }

        public Adress Adress { get; set; }
    }

PersonDbContext


public class PersonDbContext : DbContext
    {

        public DbSet<Person> Persons { get; set; }
        public DbSet<Adress> Adresses { get; set; }

        public PersonDbContext(DbContextOptions options) : base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Person>().ToTable("Persons");
            modelBuilder.Entity<Adress>().ToTable("Adresses");


        }


    }


Klasse MediaLicense


public class MediaLicense
    {
        public Guid Id { get; set; }

        public string Code { get; set; }

    }

Klasse DocumentDbContext


public class DocumentDbContext : DbContext
    {
        public DbSet<Document> Documents { get; set; }
        public DbSet<MediaLicense> Licenses { get; set; }
        public DocumentDbContext(DbContextOptions options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Document>().ToTable("Documents");
        }
    }

Thema: Content-Platzhalter mit XAML füllen
Am im Forum: GUI: WPF und XAML

Hi,

ich refactore etwas und brauche etwas Hilfe.
Viele meiner Views sind nach dem gleichen Schema aufgebaut: Header, Content1, Content2. Dabei sind in jeder View die Styles definiert sowie das Grid und alles was dazu gehört.
Da die Applikation viel MVVM benutzt, habe ich mir überlegt, ein gemeinsames ViewModel zu erstellen und ein Control, welches das Layout-Schema liefern soll. Die ViewModels erben dann vom Layout-VM und die Inhalte kann ich ja dann per Binding im ContentPresenter füllen.
In der View kann ich das Layout dann so benutzen (DataContext ist ein VM, welches von ArctionSearchResultPanelViewModel erbt):


    <local:ActionSearchResultPanel DataContext="{Binding }"/>


Jetzt habe ich aber festgestellt, dass es sich für einfache Inhalte in Content1/Content2 nicht lohnt, eine neue View und VM zu erstellen, weil sie lediglich nur einen string binden oder dergleichen.

Praktisch wäre so was:

  <local:ActionSearchResultPanel DataContext="{Binding }">
        <local:ActionSearchResultPanel.Content1>
            <TextBox Text="{Binding MyName}"></TextBox>
        </local:ActionSearchResultPanel.Content1>
        <local:ActionSearchResultPanel.Content2>
            <ListView ItemsSource="{Binding MyList}"></ListView>
        </local:ActionSearchResultPanel.Content2>
    </local:ActionSearchResultPanel>


Irgendwo habe ich die Syntax schon mal gesehen, aber ich weiß nicht wie sie genannt wird und komme daher auf kein Ergebnis beim Suchen. Die Properties, die ich bei der suche gesehen hatte, sahen nicht nach dem aus. Kann mir jemand weiterhelfen?


Zusätzliche Infos:

Die XAML für ActionSearchResultPanel sieht so aus:

 <Grid>
        <Grid.ColumnDefinitions>

        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition/>
            <RowDefinition Height="3*"/>
        </Grid.RowDefinitions>
        
        <StackPanel Orientation="Horizontal">
            <ItemsControl ItemsSource="{Binding ActionCmds}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"></StackPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </StackPanel>
        <ContentPresenter x:Name="SearchViewContent" Grid.Row="1" Content="{Binding SearchView}"/>
        <ContentPresenter x:Name="ResultViewContent" Grid.Row="2" Content="{Binding ResultView}"/>
    </Grid>

Das ViewModel sieht so aus:


private ObservableCollection<ButtonCommandViewModel> actionCmds = new ObservableCollection<ButtonCommandViewModel>();
        private BaseViewModel resultView;

        private BaseViewModel searchView;

        public ObservableCollection<ButtonCommandViewModel> ActionCmds
        {
            get { return actionCmds; }
            set { SetField(ref actionCmds, value); }
        }
        public BaseViewModel ResultView
        {
            get { return resultView; }
            set { SetField(ref resultView, value); }
        }

        public BaseViewModel SearchView
        {
            get { return searchView; }
            set { SetField(ref searchView, value); }
        }

Thema: Welche Visual Studio Extensions verwendet ihr so?
Am im Forum: Smalltalk

Wie würdest du dir denn so was vorstellen?

Thema: Welche Visual Studio Extensions verwendet ihr so?
Am im Forum: Smalltalk

Zitat
Das halte ich für eine ganz schlimme Idee; und widerspricht im weiteresten Sinne auch dem Sinn von Namespaces.

Gebe ich dir eigentlich recht. In gewissen Situationen kann das aber ganz hilfreich sein, bspw in WPF Projekten, wenn man Views und ViewModels Namespaces in seine XAML importieren will. Meistens nutze ich da 2-3 Namespaces jeweils für die Views und ViewModels, sodass ich möglichst wenig Namespaces in der XAML deklarieren muss.


Zitat
.. was nur in kleinen Teams (theoretisch) funktioniert und in großen Teams mindestens 3 mal am Tag zu Merge-Konflikten führt.

Stimmt. Aktuell sind wir ein sehr kleines Team und haben sehr viele Solutions.


Hatte mal überlegt, eine Extension mit Roslyn zu schreiben, aber kam bislang nicht dazu.

Thema: Welche Visual Studio Extensions verwendet ihr so?
Am im Forum: Smalltalk

Auf Viasfora bin ich auch schon gestoßen, sieht ganz interessant aus, aber da es ja aktuell buggy ist, wohl keine Option für mich..

Schade, dass OzCode die IDE sehr stark verlangsamt. Das habe ich allerdings auch schon befürchtet aufgrund der ganzen "Berechnungen" zur Laufzeit und die IDE ist auch so stellenweise beim Debuggen mal lahm..

Was ich mir wünschen würde:

  • Für gewisse Ordner eine Regel einführen (bspw. alle Klassen im Ordner "ViewModel" sollen von "ViewModelBase" erben)
  • Zusätzliche Debugging-Infos ohne Hover wie bspw in IntelliJ
  • Solutionübergreifende Refactorings (Namensänderungen, Namespaceänderungen - 'n kleiner Traum)
  • Template-Favoriten im Solution Explorer Kontextmenü (was soll angezeigt werden und was nicht?)