Error when using api call to send post values to controller and mapping them with a dto

I have two webpages, the first has a dropdown that allows the person to select a project & a button. When the button is submitted, it takes them to the manage users webpage and sends the Projectname to the webpage as well. The manage users webpage allows the person to assign a user to the project they selected on the previous webpage. There is a button as well, and when submitted it sends an api call with post values to my controller. The controller accepts a dto and then binds these values to the AssignUserDto. It then finds the entity associated w/ the dto username, and then maps the values from the dto to the entity so that the user has a Projectname associated with it.

It gives the error Cannot insert the value NULL into column 'description', table 'IssueTrackerDB.dbo.Projects'; column does not allow nulls. INSERT fails. The statement has been terminated. I have another post action that creates a project in the same controller, so I’m wondering if that post action is interfering with the AddUser action. Also, if I comment out the post action that creates the project and run it, it doesn’t give that error anymore. I’m receiving a 405 Method Not Allowed error. Another question is how to differentiate between the two post actions so that it doesn’t give that error.

Controller – Add User Action

[HttpPost("adduser")]
        public ActionResult AddUser([FromBody] AssignUserDto assignUserDto)
        {
            Users user = _repository.GetUserByName(assignUserDto.username);
            _mapper.Map(assignUserDto, user);
            _repository.SaveChanges();
            return NoContent();
        }

Controller – Create Project Action
// POST api/values
        [HttpPost]
        public void Post([FromBody] Projects project)
        {
            _repository.CreateProject(project);
            _repository.SaveChanges();
        }

AssignUserDto
using System;
using System.ComponentModel.DataAnnotations;

namespace IssueTracker.Dtos
{
    public class AssignUserDto
    {
        [Required]
        public string username { get; set; }

        [Required]
        public string Projectsname { get; set; }

        public AssignUserDto(string username, string Projectsname)
        {
            this.username = username;
            this.Projectsname = Projectsname;
        }
    }
}

Users Model
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace IssueTracker.Models
{
    public class Users
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int id { get; set; }

        [Required]
        public string username { get; set; }

        [Required]
        public string password { get; set; }

        [Required]
        public string email { get; set; }

        [Required]
        public string role { get; set; }

        public string? Projectsname { get; set; }

        [ForeignKey("Projectsname")]
        public virtual Projects Projects { get; set; }

        public Users(string username, string password, string email, string role)
        {
            this.username = username;
            this.password = password;
            this.email = email;
            this.role = role;
        }

        public Users()
        {

        }

    }
}

Projects Model
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace IssueTracker.Models
{
    public class Projects
    {
        public Projects(string name, string description)
        {
            this.name = name;
            this.description = description;
        }

        public Projects()
        {

        }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public string id { get; set; }

        [Required]
        public string name { get; set; }

        [Required]
        public string description { get; set; }

        
    }
}

project.js
import React, { Component } from "react";
import { useState, useEffect } from "react";
import { Grid, TextField, Button, Typography } from "@material-ui/core";
import {
    BrowserRouter as Router,
    Link,
    Route,
    Switch,
} from 'react-router-dom';
import Select from 'react-select';

const Project = () => {
    const [name, setName] = useState();
    const [description, setDescription] = useState();
    const [projects, setProjects] = useState([]);
    const [selectedValue, setSelectedValue] = useState();
    const [selectedLabel, setSelectedLabel] = useState();
    const projectlist = [];

    const handleChange = obj => {
        setSelectedValue(obj.value);
        setSelectedLabel(obj)
    }

    const post = () => {
        const requestOptions = {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                name: name,
                description: description,
            }),
        };
        fetch("/api/Project", requestOptions)
            .then((response) => response.json())
            .then((data) => {

            })
    }

    useEffect(() => {
        fetch("/api/Project")
            .then((response) => response.json())
            .then((data) => {
                setProjects(data)
            })
    }, [])

    return (
        <div>
            {projects.forEach(function (element) {
                projectlist.push({ label: element.name, value: element.name })
            })}e
            {console.log(selectedValue)}
            <body>
                <Select
                    value={selectedLabel}
                    options={projectlist}
                    onChange={handleChange}
                    isOptionDisabled={option => option.isDisabled}
                />
                <form action="#" method="POST">
                    <TextField onChange={(e) => setName(e.target.value)}> </TextField>
                    <br>
                    </br>
                    <TextField onChange={(e) => setDescription(e.target.value)}> </TextField>
                    <br>
                    </br>
                    <Button onClick={() => post()}> Create New Project </Button>
                </form>
            </body>
            <Link to={{
                pathname: '/manageusers',
                state: {
                    project_name: selectedValue
                }
            }}>Manage Users
          </Link>
        </div>
    );
}



export default Project;

manageusers.js
import React, { Component } from "react";
import { useState, useEffect } from "react";
import { Grid, TextField, Button, Typography } from "@material-ui/core";
import { FixedSizeList as List } from 'react-window';
import css from './style.css';
import Select from 'react-select';
import { useLocation } from "react-router";

const Manageusers = () => {
    const [role, setRole] = useState([]);
    const location = useLocation();
    const [project_name, setProjectName] = useState();
    const [selectedValue, setSelectedValue] = useState();
    const rolelist = [];
    const [selectedLabel, setSelectedLabel] = useState();

    const handleChange = obj => {
        setSelectedValue(obj.value);
        setSelectedLabel(obj);
    }

    useEffect(() => {
        fetch("/api/IssueTracker")
            .then((response) => response.json())
            .then((data) => {
                setRole(data)
            })
    }, [])

    const post = () => {
        const requestOptions = {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                username: selectedValue,
                Projectsname: project_name
            }),
        };
        fetch("/api/Project", requestOptions)
            .then((response) => response.text())
            .then((data) => {

            })
            .catch((error) => {
                console.log(error)
            });
    }

    const Name = () => {
        return (
            <div>
                <Grid item xs={3}>
                    <Typography component="h5" variant="h5">
                        {setProjectName(location.state.project_name)}
                    </Typography>
                </Grid>
            </div>
        )

    }

    return (
        <div>
            {role.forEach(function (element) {
                rolelist.push({ label: element.username, value: element.username })
            })}
            {console.log(selectedValue)}

            <Select name="user"
                value={selectedLabel}
                options={rolelist}
                onChange={handleChange}
                isOptionDisabled={option => option.isDisabled}
            />
            <div>
                <Button onClick={() => post()}> Add User</Button>
            </div>
            <Name />
        </div>
    );
}

export default Manageusers;

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Your const post in manageusers.js has the wrong route. You’re targeting "/api/Project" when it should probably be "/api/Project/adduser".

It looks like you are hitting the POST "/api/Project" method, it tries to insert a new Projects into the database and fails when it is missing fields. You get the 405 when you remove that method because after you remove it, there is no longer a valid POST "/api/Project"


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x