Laden...
D
Duesmannr myCSharp.de - Member
C# Softwareentwickler Münster Dabei seit 28.04.2017 161 Beiträge
Benutzerbeschreibung

Forenbeiträge von Duesmannr Ingesamt 161 Beiträge

20.02.2020 - 21:30 Uhr

Du hast das HasOne angepasst und die Migration aktualisiert?
Würde nun vermuten: nein 😉

Natürlich nicht. Ist ja auch nicht so, dass man da hätte von alleine drauf kommen können..

Ich danke dir Abt! 😃

20.02.2020 - 21:11 Uhr

Du kommst hier um ein Nullable nicht drum herum. Du verlagerst also nur jedoch löst Dein "Problem" nicht.

Kann ich dir nur zustimmen.

Wenn das Problem hier dazu gehört, dann kannst Du ruhig mehrere Fragen stellen.
Sinn der Forenregel ist nur, dass so ein Thread kein Endlosthema wird.

Problem bezieht sich auch größtenteils auf den Thread Titel.

Beim erstellen der DB, Seed ich Daten direkt zur Datenbank und erstelle da auch den "Systemuser". Den ich eventuell komplett rauslasse, aber für zukünftige Probleme gleicher Art hätte ich dann gerne einen Lösungsansatz.

In der OnModelCreating Methode habe ich diese Zeilen


User systemUser = new User
{
    FirstName = "System"
};

modelBuilder.Entity<User>().HasData(systemUser);

List<WorkItemType> workItemTypes = new List<WorkItemType>
{
    new WorkItemType
    {
        Name = "Userstory",
        CreatedById = systemUser.Id,
        ModifiedById = systemUser.Id
    },
    new WorkItemType
    {
        Name = "Task",
        CreatedById = systemUser.Id,
        ModifiedById = systemUser.Id
    },
    new WorkItemType
    {
        Name = "Epic",
        CreatedById = systemUser.Id,
        ModifiedById = systemUser.Id
    },
    new WorkItemType
    {
        Name = "Feature",
        CreatedById = systemUser.Id,
        ModifiedById = systemUser.Id
    },
    new WorkItemType
    {
        Name = "Bug",
        CreatedById = systemUser.Id,
        ModifiedById = systemUser.Id
    },
    new WorkItemType
    {
        Name = "Issue",
        CreatedById = systemUser.Id,
        ModifiedById = systemUser.Id
    }
};

foreach(WorkItemType workItemType in workItemTypes)
{
    modelBuilder.Entity<WorkItemType>().HasData(workItemType);
}

Daraus ensteht die Migration:


migrationBuilder.InsertData(
                schema: "RD",
                table: "Users",
                columns: new[] { "Id", "CreatedById", "ModifiedById", "Firstname" },
                values: new object[] { new Guid("9f5f691d-a7d6-49f7-aae6-fdd7281c1339"), null, null, "System" });

migrationBuilder.InsertData(
                schema: "RD",
                table: "WorkItemTypes",
                columns: new[] { "Id", "CreatedById", "ModifiedById", "Name" },
                values: new object[,]
                {
                    { new Guid("492ab899-8f7c-4b41-8d14-50d7281374f6"), null, null, "Userstory" },
                    { new Guid("b617a0da-1a45-444c-b13d-85acb0f22164"), null, null, "Task" },
                    { new Guid("1c69cb62-a978-4ef4-96ac-aa1442a100f2"), null, null, "Epic" }
                });

migrationBuilder.InsertData(
                schema: "RD",
                table: "WorkItemTypes",
                columns: new[] { "Id", "CreatedById", "ModifiedById", "Name" },
                values: new object[,]
                {
                    { new Guid("c31dead7-523a-4603-a271-7fde6b5b7d4c"), new Guid("9f5f691d-a7d6-49f7-aae6-fdd7281c1339"), new Guid("9f5f691d-a7d6-49f7-aae6-fdd7281c1339"), "Feature" },
                    { new Guid("120908db-e73c-4dac-b980-fb85c3ca98cf"), new Guid("9f5f691d-a7d6-49f7-aae6-fdd7281c1339"), new Guid("9f5f691d-a7d6-49f7-aae6-fdd7281c1339"), "Bug" },
                    { new Guid("caec8768-29f1-4831-ae5a-db71ae707dea"), new Guid("9f5f691d-a7d6-49f7-aae6-fdd7281c1339"), new Guid("9f5f691d-a7d6-49f7-aae6-fdd7281c1339"), "Issue" }
                });

Ich verstehe nicht, warum der einmal drei Datensätze mit null Werten bei CreatedBy und ModifiedBy hat und die restlichen Datensätze mit gefüllten Werten.

20.02.2020 - 20:48 Uhr

Danke für deine schnelle Antwort.

nur ein gut gemeinter Rat, auch damit Du mehr Freude am Code hast und schneller voran kommst: Du solltest Dir echt mal 1-2 Stunden Zeit nehmen und einfach mal die Dokumentationen grob überfliegen.

Bevor ich hier was poste, lese ich die entsprechenden Stellen in der Doku immer und immer wieder. Das hier ist nur der letzte Ausweg, was in der letzten Zeit doch relativ häufig ist.

Das kann Dir ja auch kein Spaß machen, oder? 😉

Es hält sich in Grenzen..

  1. .IsUnique(false) ist quatsch, weil das sowieso schon implizit der Fall ist. Ein Index auf FKs macht aber meistens sinn; das passt.

Lasse ich den Aufruf explizit weg, erstellt der EF Core unique Indizes. Und ich erhalte dadurch duplicate entry exceptions.

  1. Wenn Du schon die vollständige Entität geladen hast, dann ist die EF Empfehlung auch die Navigation für die Zuweisung zu nutzen und nicht nur die FK-Eigenschaft (was hier aber am Fehler nichts ändert); Navigation always wins.

Das war nur zu Testzwecken. IdR setze ich immer die Navigation Property.

Du hast im Schema eine 1:1 (HasOne-WithOne) Beziehung konfiguriert; programmierst aber eine 1:n Beziehung.

Ich bin so oft durch mein Datenbank Konzept gegangen und habe das übersehen. Nachdem ich das nun geändert habe, funktioniert es auch.

PS: "Systemuser" ist auch eher so ein Konzept von 1980.
Ist das wirklich eine Anforderung, oder ist Dir da "nichts besseres" eingefallen? Da sollte sich eigentlich immer ne bessere Lösung finden lassen.

Da fällt mir derzeit nichts besseres ein. Da ich CreatedBy und ModifiedBy nie null haben will und es auch eine History Tabelle existiert, brauche ich einen User der die Einträge erstellt hat.

PS: Ich hätte auch eine kurze Frage beim Problem von der Erstellung einer Migration. Bzw. ist das Problem der Code, der daraus entsteht. Ich will dafür nicht einen neuen Thread aufmachen. Und die Doku hilft auch nicht^^

20.02.2020 - 19:41 Uhr

Hallo, ich mal wieder..

Asp.Net Core 3.1 und EF Core 3.1

Ich habe derzeit ein kleines Problem mit meinen FK's.

Eine User Entity hat die Properties:


public Guid? CreatedById { get; set; }

public Guid? ModifiedById { get; set; }

public User CreatedBy { get; set; }

public User ModifiedBy { get; set; }

Relation und Index die ich erstelle:


builder.HasOne(b => b.CreatedBy)
    .WithOne()
    .HasForeignKey<TEntity>(b => b.CreatedById)
    .OnDelete(DeleteBehavior.Restrict);

builder.HasOne(b => b.ModifiedBy)
    .WithOne()
    .HasForeignKey<TEntity>(b => b.ModifiedById)
    .OnDelete(DeleteBehavior.Restrict);

builder.HasIndex(b => b.CreatedById)
    .IsUnique(false);

builder.HasIndex(b => b.ModifiedById)
    .IsUnique(false);

Datenbank passt auch soweit.

Ich füge dann zwei neue User hinzu:


using IServiceScope serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope();
ApplicationDbContext context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

context.Database.Migrate();

User systemUser = context.Users.FirstOrDefault(x => x.FirstName.Equals("System"));

User rd = new User
{
    Email = "*",
    CreatedById = systemUser.Id,
    ModifiedById = systemUser.Id
};

User ab = new User
{
    Email = "*",
    CreatedById = systemUser.Id,
    ModifiedById = systemUser.Id
};

context.Add(rd);
context.Add(ab);
context.SaveChanges();

Werden auch beide mit in die DB übernommen. Nur verliert rd immer den FK zu "SystemUser" und ab behält ihn.
SQL Profiler mal nachgesehen ob was nicht stimmt, aber die Datenbank bekommt den FK schon gar nicht.

In den Dokus und auch im Netz finde ich nichts dazu.
Es hat ja irgendwas mit dem SystemUser zu tun, aber was genau, keine Ahnung.

Idee woran es liegt?

Grüße
duesmannr

19.02.2020 - 14:42 Uhr

Dein Code kann auch so nie unter 2.1 funktioniert haben, denn das Prinzip der Pipelines gibt es seit OWIN - und das ist so ca. 8 Jahre her.

Doch. Ich hab es doch vor mir. Der Unterschied ist, dass kein Eintrag für


app.UseAuthorization();

existiert. Sondern nur Authentication.

Eines der größten Lücken war eine fehlerhafte Implementierung einer eigenen AuthorizeAttribute-Ableitung.

Das ist ja etwas, was ich nicht tue. Ich nutze ja das Standard Authorize Attribute.

Zum Abschluss. Danke für den Input 😃

19.02.2020 - 13:26 Uhr

Und wieso machst das, wenn ASP.NET bereits einen sicheren Automatismus hat?

Der ist sicher. Wo soll der unsichere Faktor sein? Das dass authorize Attribute mich derzeit immer wieder zur Login Page weiterleitet hat ja was zu bedeuten und ich will wissen was.

In der Dokumentation steht's.

Und wo genau?

Ansonsten hab ich solch ein Validation Code schon mehrfach hier im Forum gepostet und auch in
>
dokumentiert.

Ich mache derzeit ja gar nichts mit IP-Adressen.

"User Anmelden" gibt es im Web nicht.

Das war grob formuliert.

Ein relativ grober Fehler ist jedoch Deine Middlewares: UseAuthentication muss vor UseAuthorization erfolgen.
Man kann nicht authorisieren wenn man nicht authentifziert hat.

Da stimme ich dir zu. Aber das es so wichtig ist, in welcher Reihenfolge man die Middleware used finde ich seltsam.

Edit: Ich hab es nun umgedreht und es funktioniert.
Das Authorize Attribute lässt mich nun durch. Daher verstehe ich dann immer noch nicht ganz genau, wo die Authentication unsicher sein soll.

Im Debug logging (beachte dazu das LogLevel) steht der Grund, wieso AuthN oder AuthZ fehltschlägt.

Dann debugge ich das nochmal genauer.

19.02.2020 - 11:06 Uhr

im Grunde kann ich nicht wirklich weiterhelfen - du versuchst hier quasi eine manuelle Cookie-Authentifizierung oder?

Ja versuche ich.

Fakt ist: Was du dort tust ist kein für ASP.NET Core nachvollziehbarer Login, womit du eine Art Authentication-Loop für den User gebaut hast.

In .Net Core 2.1 funktioniert es wunderbar. Nur in 3.1 nicht mehr.

-> Du denkst, dass du den Benutzer erfolgreich anmeldest

Ich denke? Was macht dann HttpContext.SignIn() ? Den User anmelden eig.

-> siehe Schritt 1 (ASP.NET Core stellt fest: User ist nicht angemeldet) und der Loop beginnt von vorn

Ich habe noch keine konkrete Information dazu gefunden, wie das Attribut den Zugriff authoriziert.

Falls du das mit manuellen Cookies machen möchtest würde ich dir folgende Seite empfehlen:

>

Habe die Seite dabei die ganze Zeit offen 😃

19.02.2020 - 08:56 Uhr

Hey, ich schon wieder^^

Das Problem ist, wenn ich mich erfolgreich authentifiziere und ich mich mit SignInAsync anmelde, werde ich zum HomeController weitergeleitet.
Das Authorize leitet mich direkt wieder zur Login Page zurück, weil weiß ich nicht.

Die ValidateAsync Methode habe ich überprüft, das Cookie wird nicht rejected oder ich werde ausgeloggt.

Ich habe es auch mit einem Custom Authorize Attribute getestet um den Context zu überprüfen.
In dem Context bin ich angemeldet und authenticated.

Die Authentifizierung habe ich genau so in einem Asp.Net Core 2.1 Projekt und da läuft es einwandfrei..

Aber warum Authorize mich nicht durchlässt, ich weiß es nicht.
Habt Ihr Ideen?

Hier ist die Konfiguration:

HomeController.cs


public class HomeController : Controller
{
    [Authorize]
    public IActionResult Index()
    {
        return this.View("Index");
    }
}

Startup.cs


public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.LoginPath = "/auth/login/";
                options.ExpireTimeSpan = TimeSpan.FromDays(7);
                options.Events.OnValidatePrincipal = ValidateAsync;
            });

        services.AddControllersWithViews();

        services.AddAntiforgery();

        services.AddDbContext<ApplicationDbContext>((serviceProvider, options) =>
        {
            options.UseSqlServer(this.Configuration.GetConnectionString("DefaultConnection"));
            options.EnableSensitiveDataLogging();
        });
    }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if(env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();
        app.UseAuthentication();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }

public static async Task ValidateAsync(CookieValidatePrincipalContext context)
    {
        context = context ?? throw new ArgumentNullException(nameof(context));

        String userId = context.Principal.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier)?.Value;

        if(userId == null)
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return;
        }

        ApplicationDbContext dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
        User user = await dbContext.Users.FindAsync(Guid.Parse(userId));

        if(user == null)
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return;
        }

        if(!user.StaySignedIn && 
            user.LastLogin != null && 
            (user.LastLogin.Subtract(TimeSpan.FromDays(1)) > DateTimeOffset.Now))
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return;
        }
    }

AuthController.cs


[Route("/login")]
    [Route("/auth/login")]
    public async Task<IActionResult> Login([FromForm]LoginModel loginModel)
    {
        Claim nameIdentifier = new Claim(ClaimTypes.NameIdentifier, user.Id.ToString());

        ClaimsIdentity userIdentity = new ClaimsIdentity(new List<Claim> { nameIdentifier }, CookieAuthenticationDefaults.AuthenticationScheme);
        ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(userIdentity);

        await this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
        return this.RedirectToAction("Index", "Home");
    }

05.02.2020 - 18:01 Uhr

Moin @Coffeebean,

ich habe sogar vor dem Posten des Beitrags nochmal in den Post zum richtig Posten geguckt.

Aber da die beiden Fragen auf ein Thema belaufen (EF Core Relations) bin ich davon ausgegangen, dass ein Thread in dem Fall in Ordnung ist.
Ich kann es gerne noch ändern und zwei Threads daraus erstellen.

@Abt
Das es sich immer auf das Child auswirkt, weiß ich. Aber wie erkenne ich, welche Properties die Childs sind?

Das mit dem Zeitstempel, okey..
Ich mache es derzeit so:


IEnumerable<IMutableEntityType> classes = modelBuilder.Model.GetEntityTypes().Where(x => x.ClrType.IsSubclassOf(typeof(Base)));

            foreach(IMutableEntityType item in classes)
            {
                modelBuilder.Entity(item.ClrType, x =>
                {
                    x.Property("CreatedOn").HasDefaultValueSql("getdate()");
                    x.Property("ModifiedOn").HasDefaultValueSql("getdate()");
                    x.Property("Id").HasDefaultValueSql("newid()");
                    x.Property("CreatedById").IsRequired(false);
                    x.Property("ModifiedById").IsRequired(false);
                });
            }

04.02.2020 - 22:54 Uhr

Verwendetes System:
Asp.Net Core 2.1 mit EF Core 2.1

1. Frage
Ich habe diese Basis Klasse:

public abstract class Base
{
    public Guid Id { get; set; }

    public Guid? CreatedById { get; set; }

    public Guid? ModifiedById { get; set; }

    public DateTime CreatedOn { get; set; } = DateTime.Now;

    public DateTime ModifiedOn { get; set; } = DateTime.Now;

    public User CreatedBy { get; set; }

    public User ModifiedBy { get; set; }
}

Die habe ich, weil ich die Eigenschaften für fast jede Klasse benötige.
Dann habe ich bspw. diese Klasse noch:

public class Access : Base
{
    public String Name { get; set; }
}

Alle Relations die ich habe, erstelle ich mit Hilfe der Fluent API.
In dem Fall wäre es:

modelBuilder.Entity<Access>()
    .HasOne(u => u.CreatedBy)
    .WithOne()
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Access>()
    .HasOne(u => u.ModifiedBy)
    .WithOne()
    .OnDelete(DeleteBehavior.Restrict);

Das passiert derzeit in ca. 20 Klassen so. Der Hintergrund ist, dass CreatedBy und ModifiedBy nicht geleert werden sollen (die ID soll bei behalten werden), bzw. der ganze Datensatz gelöscht werden soll, wenn der/ein User gelöscht wird.

Es heißt ja, dass der Child Datensatz standardmäßig gelöscht wird, wenn der Parent gelöscht wird. Was in dem Fall nicht passieren sollte, weil es eine 1:1 Relation ist und es keine Child/Parent Abhängigkeit gibt, oder? Also ist der Aufruf von OnDelete überflüssig?

Macht es ein Unterschied, wenn ich von der Klasse Access anfange die Relation zu erstellen? Also in dem Fall gehe ich gerade auf

modelBuilder.Entity<Access>()

und erstelle die 1:1 Relation.
Ich kann die Relation ja auch von der Base Klasse aus erstellen.

2. Frage
Zweiteres wo ich gerade dran hänge ist bei M:N Relations.
Nehmen wir an, wir haben die beiden Klassen:

  1. Students
  2. Courses

Students haben N Courses und Courses haben N Students => M:N Relation => 3. Tabelle um die Relation auf zwei 1:N Relations aufzuteilen => StudentCourse Klasse wird erstellt.

In dem Beispiel was ich vor mir liegen habe, wird so die Relation erstellt:


modelBuilder.Entity<StudentCourse>().HasKey(sc => new { sc.SId, sc.CId });

modelBuilder.Entity<StudentCourse>()
    .HasOne<Student>(sc => sc.Student)
    .WithMany(s => s.StudentCourses)
    .HasForeignKey(sc => sc.SId);


modelBuilder.Entity<StudentCourse>()
    .HasOne<Course>(sc => sc.Course)
    .WithMany(s => s.StudentCourses)
    .HasForeignKey(sc => sc.CId);

Macht es einen Unterschied, wenn ich bei der Entity Course anfange und dann auf die Relation Tabelle zugreife um die Relation zu erstellen? Und als zweiten Step dann bei der Entity Student weitermache? Also das ich anstelle von Entity<StudentCourse> einmal Student und einmal Course enthalten ist. Hoffe Ihr versteht was ich meine, will nicht zu viel Code posten.

Oder wie ist die "vorgeschriebene" Art das zu bewerkstelligen?

Grüße und einen schönen Abend
duesmannr

29.10.2019 - 09:10 Uhr

Also für die Entitäten neue Klassen erstellen mit benötigten Werten.

29.10.2019 - 08:48 Uhr

@Abt hab dann doch dazu auch eine Frage.

  • Wenn Du Deine Navigation Properties ohne virtual deklarierst, brauchst Du eigentlich kein Include

Hat er doch? Oder übersehe ich die gerade lediglich? Habe meine auch ohne virtual deklariert und brauche dennoch das Include().

I.d.R. ist es keine gute Idee, dass Du Datenbank-Enitäten direkt aus der API raus gibst.

Wie denn sonst, wenn man im ApiController mit dem DBContext arbeitet?

Du nimmst bei deinem Talk einen dritt Anbieter. Den du Befehle mitteilst.


        private readonly IMediator _mediator;

        public AuthorsController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpGet]
        public async Task<ActionResult<IEnumerable<AuthorApiViewModel>>> Get()
        {
            IList<Author> result = await _mediator.Send(new GetAllAuthorsQuery());

            IEnumerable<AuthorApiViewModel> viewModels = result.Select(AuthorApiMapper.MapToApiModel);
            return Ok(viewModels);
        }

Aber, wenn man keinen dritt Anbieter nutzt, kann man doch nichts anderes machen, als die Entität zurückzugeben?

Grüße

12.08.2019 - 00:10 Uhr

Danke für deine Antwort und dein Feedback.

Die Klasse sollte eher UserEntity statt RD_User heissen; RD_User würde ohnehin gegen jede Namenskonvention verstoßen - vor allem die von EF Core (von RD_Class ganz zu schweigen).

Ich finde zu EF Core keine Namenskonventionen und habe davon auch nichts gelesen.

Aber mein eigentliches Problem habe ich auch gelöst bekommen.

Grüße

11.08.2019 - 01:21 Uhr

Nabend,

ich bastel mir gerade eine DB zusammen mit EF Core 2.1.

Ich habe zwei Klassen:


public class RD_User
{
    [Key]
    public Guid Id { get; set; }
}


public class RD_Class
{
    [Key]
    public Guid Id { get; set; }

    public Guid CreatedById { get; set; }


    public Guid ModifiedById { get; set; }



    [ForeignKey("CreatedById")]
    public RD_User CreatedBy { get; set; }
    [ForeignKey("ModifiedById")]
    public RD_User ModifiedBy { get; set; }
}

Habe ich bspw. "ModifiedBy" auskommentiert, funktioniert die Migration.
Migriere ich das mit der Property, bekomme ich einen Fehler, der im Endeffekt sagt, dass es zwei Relations gibt und nicht weiß, was zu was gehört. (Internet: Stichwort "InverseProperty". Aber ich habe in der User Class keine.)

Genaue Exception:> Fehlermeldung:

System.Data.SqlClient.SqlException: 'Introducing FOREIGN KEY constraint 'FK_Classes_Users_ModifiedById' on table 'Classes' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.'

Im Internet finde ich keine Lösung, ohne zusätzliche Properties zu erstellen, um das Problem zu lösen.
Weil ich in der User Class eig. keine weiteren Properties dazu haben möchte, weil ich die beiden Properties in Class in n Klassen haben möchte.

Habt Ihr eine Idee?

Mit der Fluent API funktioniert es auch nicht.

Grüße

P.S.:
Kennt Ihr ein Beispiel, wie ich z.B. auf die gleiche Klasse referenzieren kann?
Also wenn ich die beiden Properties in RD_User ebenfalls einfüge und auf die gleiche Klasse referenziere. Habe dazu auch noch keinen Ansatz gefunden.

23.10.2018 - 16:45 Uhr

Ja war schlecht ausgedrückt meinerseits.

Aber danke für die Informationen. Habe daraus ein wenig gelernt.

Schönen Feierabend.

Es gibt aber prinzipiell zwei Arten von Sessions:
Die "Session Fixation", die mit der ID arbeitet und damit nicht manipulierbar ist und eine Raw Session Handling, der alle Session Values roh in den Cookie schreibt - das ist manipulierbar.

Bei Sessions allgemein: sie lassen sich im Vergleich einfach hijacken - vor allem wenn man mit Cookie-less Sessions arbeitet und damit die ID in der lesbaren URL steckt; damit auch durch HTTPS nicht geschützt ist.
Daher sollte man immer mit Session Fixation und bei einer UI-WebApp mit Cookies arbeiten.

Gut zu wissen, danke. Muss man sich doch noch mal genauer mit auseinander setzen.

23.10.2018 - 16:29 Uhr

Nein will ich nicht, dass war nur ein Beispiel!
Damit man das Problem besser versteht.

Mein Arbeitskollege hat behauptet, dass der User die Sessions manipulieren kann und sucht deswegen eine andere Methode.

Und dazu wollt ich eure/deine Meinung hören.

23.10.2018 - 16:26 Uhr

Das die Authentifizierung alles automatisch gemacht wird, ist mir bekannt.
Das war lediglich ein Beispiel, wenn man den Login komplett selbst erstellt ≤ Beispiel.
Um dann in der Session zu speichern, ob der User eingeloggt ist und welcher User das ist etc.

23.10.2018 - 16:20 Uhr

Es geht nicht um die eigentlichen Daten.
Sondern "UserAuthenticated = true" und das würde man dann wieder Abfragen, falls der User wiederkommt. (War unverständlich ausgedrückt)

Also, wenn man die Session von der HttpContext Klasse nimmt, bekommt der User nur die ID und kann damit im Endeffekt nichts machen?

23.10.2018 - 16:05 Uhr

Guten Tag,

ein Arbeitskollege und ich Fragen uns, wie man Daten serverseitig speichern kann, ohne das der User diese Daten manipulieren kann.

Es geht um Asp.Net Core und Framework.

Microsoft bietet die HttpContext Klasse an um mit Sessions zu arbeiten.
Wird die Session mit an den User geschickt? Dieser könnte ja beim nächsten Besuch der Website die Session manipulieren.

Der Arbeitskollege hat dann das "TempDataDictionary" angesprochen, ob das Werte temporär speichern kann? Bspw. ob der User eine gültige Lizenz hat etc.

Oder sind wir beide auf einem falschen Dampfer?

Sind auch am Dokumentationen lesen, aber uns ist noch keine Erleuchtung gekommen.

Ein Feedback wäre schön.

Grüße

13.06.2018 - 20:39 Uhr

Passiert das auch auf dem gleichen Rechner?

Meistens, wenn ich den Rechner wechsel. Aber ja auch.

Haben wir einfach "gelöst" indem wir den AutoScaleMode auf None gesetzt haben; aber das kommt mit dem Nachteil dass das Formular nicht wirklich skaliert wenn man auf unterschiedlichen DPI unterwegs ist.

Das ist einer der ersten Eigenschaften die ich immer auf None setze.

13.06.2018 - 13:50 Uhr

Alles im Designer.

Wenn ich die Form igendwann später wieder öffne sind die Controls irgendwo auf der Form.
Im Designer sind die Werte dann auch verändert, wie ich angegeben habe.

13.06.2018 - 10:41 Uhr

Guten Tag,

ich habe ein UserControl, worauf eine TextBox und ein Label ist.

Hier einmal kurz ein Stück Code:


//Das ist die Erstellung des eigentlichen UserControls
        private void InitializeComponent()
        {
            this.labelBorder = new System.Windows.Forms.Label();
            this.textBoxInput = new Dousy.Class.Control.TextBox();
            this.SuspendLayout();

            this.labelBorder.Location = new System.Drawing.Point(0, 24);
            this.labelBorder.Size = new System.Drawing.Size(100, 2);
            this.textBoxInput.Location = new System.Drawing.Point(0, 0);
            this.textBoxInput.Size = new System.Drawing.Size(100, 26);

            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.labelBorder);
            this.Controls.Add(this.textBoxInput);
            this.Name = "UserControlTextBox";
            this.Size = new System.Drawing.Size(100, 26);
            this.Load += new System.EventHandler(this.UserControlTextBox_Load);
            this.ResumeLayout(false);
        }

Das Problem ist. Wenn ich das UserControl einer Form hinzufüge, die Location und Größe mit dem Designer anpasse und die Form schließe (nachdem ich alles gespeichert habe). Und ich später die Form wieder öffne, sind alle UserControls irgendwo anders. D.h. das die Größe davon Random ist und die Location auch.

Auf der Form sieht der Code dann so aus:


//Einstellung des UserControls auf der Form
        private void InitializeComponent()
        {
            this.userControlTextBoxPassword = new Dousy.Class.Control.UserControlTextBox();

            // 
            // userControlTextBoxPassword
            // 
            this.userControlTextBoxPassword.BorderColor = System.Drawing.Color.Gray;
            this.userControlTextBoxPassword.BorderColorHover = System.Drawing.Color.DarkGray;
            this.userControlTextBoxPassword.BorderColorHoverActive = true;
            this.userControlTextBoxPassword.BorderColorSelected = System.Drawing.Color.Orange;
            this.userControlTextBoxPassword.BorderColorSelectedActive = true;
            this.userControlTextBoxPassword.BorderDirection = System.Windows.Forms.DockStyle.Bottom;
            this.userControlTextBoxPassword.BorderWidth = 3;
            this.userControlTextBoxPassword.Location = new System.Drawing.Point(16, 438);
            this.userControlTextBoxPassword.Margin = new System.Windows.Forms.Padding(36, 33, 36, 33);
            this.userControlTextBoxPassword.Name = "userControlTextBoxPassword";
            this.userControlTextBoxPassword.Placeholder = true;
            this.userControlTextBoxPassword.PlaceholderActiveForeColor = System.Drawing.Color.Gray;
            this.userControlTextBoxPassword.PlaceholderFont = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.userControlTextBoxPassword.PlaceholderForeColor = System.Drawing.Color.Gray;
            this.userControlTextBoxPassword.PlaceholderText = "Kennwort";
            this.userControlTextBoxPassword.Size = new System.Drawing.Size(403, 30);
            this.userControlTextBoxPassword.TabIndex = 4;
            this.userControlTextBoxPassword.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
            this.userControlTextBoxPassword.TextBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
            this.userControlTextBoxPassword.TextFont = new System.Drawing.Font("Arial", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.userControlTextBoxPassword.TextForeColor = System.Drawing.Color.White;
            this.userControlTextBoxPassword.TextInput = "";
            this.userControlTextBoxPassword.UseSystemPasswordChar = true;
        }

Habt Ihr eine Idee woran es liegen könnte?

Habe hier einmal die Location und die Size von dem UserControl wo dieser lag:


Location: 41; 1295
Size: 1068; 89

Oder kann es daran liegen das ich das Projekt auf zwei verschiedenen Geräte bearbeite?
Die aber die gleiche Auflösung haben. Mir fällt auch auf, dass andere Controls auch nicht mehr auf deren Ursprungspositionen sind, wie auf dem anderen Gerät.

05.06.2018 - 08:49 Uhr

Es scheint zu funktionieren.
Danke!

04.06.2018 - 20:28 Uhr

Hallo,

ich habe vorerst diese Klasse:


public class TestTextBox : System.Windows.Forms.TextBox
{
    [Browsable(true)]
    public override bool AutoSize
    {
        get => base.AutoSize;
        set => base.AutoSize = value;
    }
}

Wenn ich im Designer die TextBox einfüge und die AutoSize Property auf false setze, kann ich wie erwartet die Höhe der TextBox ändern.
Wenn ich jedoch das Programm dann starte, hat die TextBox eine Höhe, wie wenn die Property wieder auf true ist.

Warum ist das so?
Auch wenn ich eine weitere Variable nehme um den Wert zu speichern, bringt dies auch nichts.

Danke für die Hilfe.

PS: Ich könnte im Konstruktor das hier ausführen:


this.AutoSize = false;

aber dann hat jede TextBox den Wert false und das soll nicht so sein.

07.02.2018 - 22:38 Uhr

Mit


control.GetType()

funktioniert es auch, ohne zu wissen, welches Control es eig. ist.

07.02.2018 - 17:08 Uhr

Damit ich auf die verschiedenen Properties von den Controls drauf zugreifen kann.
Beispielsweise hat das Label Control die Property "TextAlign". Die eine Textbox
nicht hat.

07.02.2018 - 11:23 Uhr

Das stimmt, aber das Konstrukt wäre sehr lang, wenn ich 10 verschiedene Controls darin hätte.

07.02.2018 - 10:17 Uhr

z.B. den Typ mittels

  
control.GetType()  
  

Das sollte funktionieren und somit habe ich keine Fragen mehr.

oder direkt per Cast:

  
Label label = control as Label;  
if (label != null)  
{  
    // label.  
}  
  

Das würde nicht funktionieren, wenn ich noch Panels etc. drin habe, aber ich nicht weiß, welches Item was ist.

Ich bedanke mich für Eure Hilfe.

07.02.2018 - 08:45 Uhr

@Th69
danke mit einer Extension Method funktioniert es.

Deklaration:


ControlList list = new ControlList(destinationPanel)
{
     Control label1 = new Label()
     {
          Text = "LabelText",
          Tag = new AdvControlProperties()
     },
     Control textbox1 = new TextBox()
     {
          Visible = false,
          Tag = new AdvControlProperties()
     }
};

Eine Frage bleibt mir aber noch.
Jetzt habe ich in dieser Liste zwei Controls.
Kann ich irgendwie herausfinden welches Control das eig. ist?

06.02.2018 - 16:25 Uhr

Das sieht gut aus. Kannte die Property nicht.

Wenn ich dann das Label deklariert habe mit der AdvControlProperties Klasse, kann ich dann nur auf die Properties der Klasse mit


AdvControlProperties properties = newControl.Tag as AdvControlProperties;

double factor = properties.Factor;

zugreifen? Oder gibt es eine kürzere Variante?

06.02.2018 - 08:51 Uhr

Ich könnte jedes Control ableiten lassen was ich brauche und die zwei Properties hinzufügen.

Aber ich will nur eine Klasse die die zwei Properties hat und ich mit dieser Klasse jedes Control "darstellen" kann.

Am liebsten würde ich z.B.


Control newControl = new Label();

sodass "newControl" ein Label ist, aber die zwei Properties hat.

Hatte erst an Generic gedacht, aber das bringt mich auch nicht weiter.

Hoffe das ist verständlicher.

Mit freundlichen Grüßen

05.02.2018 - 22:58 Uhr

Hallo,

ich will auf meine UI eine andere Navigation haben. Ich habe dafür ein Panel was über die gesamte Breite geht. Ich habe zwei Klassen erstellt, einmal die Liste die die Controls verarbeitet und eine Controls Klasse, die ich erstellt habe um zwei weitere Properties für jedes Control zu haben, was in diese Liste kommen soll.

In dieses Panel adde ich Controls hinzu und die Größe der Controls wird anhand des Panels errechnet, hier ein Codeschnipsel:


public class ControlList : List<System.Windows.Forms.Control>
{
        /// <summary>
        /// In which panel the list is displayed
        /// </summary>
        public Panel DestinationPanel { get; }

        public ControlList(Panel destinationPanel)
        {
            this.DestinationPanel = destinationPanel;
        }

        public new void Add(System.Windows.Forms.Control control)
        {
            base.Add(control);
            this.DestinationPanel.Controls.Add(control);
            this.ChangeSize(); //Ändert die Größe von allen vorhanden Controls
        }
}

Und hier einmal die Control Klasse


public class Control
{
        public double Factor { get; set; }
        public bool Selected { get; set; }

        //Hier die Control Property, damit ich darauf von außen drauf zugreifen kann
        public System.Windows.Forms.Control SourceControl { get; set; }

        /// <summary>
        /// Override the mouse enter event from the source control
        /// </summary>
        public event EventHandler MouseEnter;

        private void AddEventsToControl()
        {
            this.SourceControl.MouseEnter += SourceControl_MouseEnter;
        }

        private void SourceControl_MouseEnter(object sender, EventArgs e)
        {
            this.MouseEnter?.Invoke(this, e);
        }
}

Das ganze funktioniert auch. Ich kann in meiner Liste auch die weiteren Properties zugreifen. Nur finde ich das ganze sehr unschön.

In der Control Klasse habe ich das Event, damit ich als object sender diese Control Klasse habe und nicht nur das SourceControl.

Ich will in dieser Liste, Labels, Textboxen, Panels etc. hinzufügen können. Aber ich bekomme es zurzeit nicht besser hin.

Habt Ihr Anregungen, Verbesserungen?

Mit freundlichen Grüßen

13.01.2018 - 16:24 Uhr

Mh okey.
Eigentlich mache ich nichts an der Größe.

Da meine Form borderless ist, benutze ich:


        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();

die .dll um meine Form zu verschieben und die Größe zu ändern.

11.01.2018 - 16:02 Uhr

Guten Tag,

wenn man ein Programm mit dem Mauszeiger zum Bildschirm Rand verschiebt, kommt ein zu sehendes transparentes Fenster, was anzeigt welche Größe das Programm haben wird, wenn man es in dem Augenblick los lässt. ( Rechter & Linker Rand: Fenster nimmt die hälfte vom Bildschirm ein. Oben: Fenster wird zum Vollbild Fenster.)
Hoffe Ihr versteht was ich damit meine.

Mein Problem, wenn ich meine Form dahin verschiebe, passiert nichts. Sehe weder das transparente Fenster und es wird daraufhin auch nicht vergrößert.

Da ich nicht weiß, wie diese Funktion heißt, würde ich mich über einen Denkanstoß freuen.

Habt ihr Schlüsselwörter für mich ? oder auch schon eine Erklärung warum dies so ist und einen Ansatz?

Mit freundlichen Grüßen

20.10.2017 - 08:59 Uhr

Joar, hab mich von dir aufs Glatteis führen lassen.

Beabsichtig war das nicht.
Und mit SvgDocument.Heigt/Width funktioniert es auch. Ich bedanke mich sehr bei dir 😃

18.10.2017 - 19:50 Uhr

@MrSparkle

Aufjedenfall danke. Naja alles Pfusch hier.. 😄

Werde mein Projekt einfach in Wpf übertragen, auch wenn ich von Xaml keine Ahnung habe, aber ja 😃

18.10.2017 - 16:46 Uhr

Fehlt da nicht noch der Kreis außen herum?

@ThomasE.

Eig. nicht. Das letzte Bild was ich hochgeladen habe, habe ich frisch von Flaticon heruntergeladen, um es an einer anderen Svg Datei auszutesten.

In dem .rar Archiv ist jetzt einmal die originale .Svg Datei und einmal die gezeichnete Bitmap Datei. Die gezeichnete Datei, muss man nicht öffnen, da man kaum was sieht, weil die kein Hintergrund hat. Wenn du die einfach markierst siehst du, dass das gezeichnete Bild oben links in der Ecke ist.

18.10.2017 - 16:17 Uhr

@MrSparkle

~~Das was gezeichnet wird, passt ja, soweit ich es verstehe.
Aber warum das nicht richtig in der PictureBox angezeigt wird, verstehe ich nicht.

Und wenn ich das gezeichnete Bild speichere, wird das Symbol ganz normal angezeigt, zwar verpixelt, aber normal.~~

Wenn man das Foto von Windows löschen will, sieht man ja ein Vorschaubild und es sieht so aus, als wenn das Symbol auch oben links in der Ecke hängt. Also müsste ja was mit dem .Draw() was nicht passen.

Also im Endeffekt wird die Grafik bei mir nicht richtig gezeichnet.

18.10.2017 - 15:54 Uhr

@ThomasE.

Eig. nicht. Das letzte Bild was ich hochgeladen habe, habe ich frisch von Flaticon heruntergeladen, um es an einer anderen Svg Datei auszutesten.

Und hier ein Bild von meinen selbst erstellten mit Illustrator. Die ich dann als .Svg exportiere.

18.10.2017 - 15:47 Uhr

@LaTino

Macht Sinn was du sagst und das es keine "Raketenwisschenschaft" ist, ist mir kla 😄

Aber selbst, wenn ich den Code 1:1 wie du habe, funktioniert es nicht. Auch mit Überlegen komme ich nicht weiter.


 string Path = String.Format("{0}Resources\\Vector\\", System.IO.Path.GetFullPath(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\")));
Svg.SvgDocument doc2 = Svg.SvgDocument.Open(Path + "test.svg");
pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;
pictureBox1.Image = doc2.Draw(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);

18.10.2017 - 14:06 Uhr

@ThomasE.

habe ich beides mal ausprobiert, funktioniert beides nicht. Warum kann ich dir nicht sagen.

@LaTino

Wie soll ich das denn in der richtigen Größe rendern?

18.10.2017 - 09:19 Uhr

@LaTino

Width und Height kann man ja in der Draw Methode festsetzen.
Mein Ansatz ist dieser:


Svg.SvgDocument doc2 = Svg.SvgDocument.Open(Path + "Next.svg");
picNext.Image = doc.Draw(picNext.Width, picNext.Height);

Da passt der Vektor zwar in die PictureBox, aber nicht richtig, bzw. nicht mittig.

Und was dabei raus kommt:

17.10.2017 - 21:43 Uhr

@MrSparkle

ich würde was anderen verwenden, wenn ich WPF benutzen würde.
Ich benutze Winforms.

17.10.2017 - 18:20 Uhr

Guten abend,
ich benutze ich meinem Programm Svg Dateien, da Sie kein Qualitätverlust haben.
Ich habe alle meine Svg Dateien ca. unter 50x50 Pixel erstellt.
Die Bibliothek die ich benutze ist die: https://github.com/vvvv/SVG

Nun habe ich eine PictureBox die 55x55 Pixel groß ist und benutze den folgenden Code:


Svg.SvgDocument doc = Svg.SvgDocument.Open(Path + "Play.svg");
picPlay.BackgroundImage = doc.Draw();

Das funktioniert auch. Habe nun jedoch auch eine PictureBox von einer Größe von 40x40 Pixel und benutze den gleichen Code.

Im Anhang grafisch dargestellt. Habt ihr Ideen?
Hatte erst daran gedacht, das Foto zu skalieren aber wüsste nicht wie mit der Bibliothek.

Mit freundlichen Grüßen

17.10.2017 - 18:15 Uhr

Nachdem Beispiel was funktionierte, habe ich eine neue Form bzw. UserControl erstellt und Schritt für Schritt die Controls gedockt. Funktioniert nun tadellos, danke 😃

13.10.2017 - 18:13 Uhr

Ich habe das jetzt in einem neuen Projekt mal dargestellt, jetzt ist doch noch kurioser als voher..

Ja deins funktioniert einwandfrei. Ich kann meine Panel zB. garnicht rechts und links docken, weil sie sonst in das untere Panel reingehen.

Gucks dir einfach mal an.

Edit:
In dem hochgeladenen Projekt, musst du im rechten Panel den Anchor nochmal setzen.

13.10.2017 - 17:02 Uhr

@inflames2k

Das die sich gegenseitig ausschließen weiß ich, sollte nur als Darstellung dienen. Das wenn ich egal was ich davon benutze, es nicht funktioniert..

Wäre nett, danke.

13.10.2017 - 16:44 Uhr

Guten Tag,
ich würde hier nicht schreiben, wenn ich nicht weiterkomme.
Im Anhang ist ein Bild von meiner Form. Jedes verschieden farbige Element ist ein Panel, mit den Eigenschaften die dran stehen.

Ich arbeite mit Anchor, weil wegen verschiedener Form Größe.

Wenn ich die Form von Links nach Rechts verkleiner oder andersrum, skalieren die Controls richtig.
Das linke und rechte Panel bleiben gleich groß, das untere und das in der Mitte werden kleiner.

Wenn ich die Form von unten nach unten größer mache, funtkioniert auch alles. Das untere Panel bleibt gleich groß, dass rosane, gelbe und hellblaue Panel werden auf der Y Größe größer.

Verkleiner ich jedoch die Form von unten, verkleinert sich das untere Panel, bis es garnicht mehr da ist und die anderen drei Panels werden auch einfach "verschlungen" aber nicht kleiner skaliert.

Wenn ich die Form von oben nach unten verkleiner, verschwindet das untere Panel auch, sowie dann die anderen drei auch wieder.

Soweit wie ich es verstehe, liegt alles am unteren Panel. Aber egal wie ich die Anchor setze oder die Dock Eigenschaft auf Bottom setze, es ändert sich nicht.

Habt ihr Vorschläge?

Mit freundlichen Grüßen

P.S.: Das ganze ist ein UserControl, mit einer bestimmtem Größe. Dieses wird auf einer Form angezeigt. Die Form ist in der Y Größe größer und zeigt über dem UserControl noch eine Leiste an, mit dem Programm Namen, Schließen Button etc.