-1

Fairly new to this but I have been trying to create a ASP.NET website to archive files. I want to capture the Windows username so when the user inserts a file, a record is kept of who inserted it. I have a table of users that will be using the site, giving the username a reference for records. When I am testing in a development environment everything works correctly and I can see the record created. However, on the server no record is being created and I get this returned to me:

'The INSERT statement conflicted with the FOREIGN KEY constraint 
"FK_Person_BoxArchive_LastUpdate". The conflict occurred in database 
"BoxManagement", table "dbo.Person", column 'PersonID'.###-1###'

I have tried enabling Windows Authentication in IIS and tried using these:

string userName = HttpContext.Current.User.Identity.Name.Replace(".", " ");
WindowsIdentity identity = HttpContext.Current.Request.LogonUserIdentity;

The code I am using to pass the username down to the stored procedure is:

string userName = Environment.UserName.Replace(".", " ");
int userID = -1;
DataTable database = new DataTable();
using (SqlConnection con = new SqlConnection(dbString))
using (SqlCommand cmd = new SqlCommand("GetUserID", con))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@userName", Environment.UserName);
    con.Open();

    using (SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
    {
        rdr.Read();
        userID = rdr.GetInt32(rdr.GetOrdinal("PersonID"));
        rdr.Close();
    }
}

And the stored procedure is just

SELECT PersonID FROM Person WHERE WindowsName = @userName

Not sure I am looking in the right places but hopefully, this is enough to be pointed in the right direction.

EDIT:

This is the code I am using to insert the file:

DataTable database = new DataTable();
string dbString = ConfigurationManager.ConnectionStrings["connArchiveDatabase"].ConnectionString;
using (SqlConnection con = new SqlConnection(dbString))
using (SqlCommand cmd = new SqlCommand("dbo.InsertAccountFile", con))
{
    try
    {
        int FileType = Int32.Parse(ddlInAccFileType.SelectedValue);
        string policyNumber = "";
        DateTime closedPolicy = new DateTime(1900, 01, 01);

        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Parameters.AddWithValue("@boxID", ddlInAccBox.Text);
        cmd.Parameters.AddWithValue("@policyNumber", policyNumber);
        cmd.Parameters.AddWithValue("@fileReference", tbInAccReference.Text);
        cmd.Parameters.AddWithValue("@archivedbyID", userID);
        cmd.Parameters.AddWithValue("@dateArchived", archivedDate);
        cmd.Parameters.AddWithValue("@closedPolicy", closedPolicy);
        cmd.Parameters.AddWithValue("@closedFile", tbInAccClosedDate.Text);
        cmd.Parameters.AddWithValue("@filetypeID", FileType);
        cmd.Parameters.AddWithValue("@comment", tbInAccComment.Text);
        cmd.Parameters.AddWithValue("@expectedDestruction", destructionDate);
        cmd.Parameters.AddWithValue("@lastupdateID", userID);
        cmd.Parameters.AddWithValue("@updatedDate", updateDate);

        SqlParameter archiveParameter = new SqlParameter
        {
            ParameterName = "@boxArchiveID",
            SqlDbType = SqlDbType.Int,
            Direction = ParameterDirection.Output
        };

        SqlParameter messageParameter = new SqlParameter
        {
            ParameterName = "@returnMessage",
            SqlDbType = SqlDbType.VarChar,
            Size = 255,
            Direction = ParameterDirection.Output
        };

        cmd.Parameters.Add(archiveParameter);
        cmd.Parameters.Add(messageParameter);

        con.Open();
        cmd.ExecuteNonQuery();

        string returnMessage = messageParameter.Value.ToString();

        ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "alertMessage", "alert('" + returnMessage + "###" + archiveParameter.Value.ToString() + "###" + "')", true);
        }

        catch (Exception ex)
        {
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "alertMessage", "alert('" + ex.Message.ToString() + "')", true);
            return;
        }

        finally
        {
            con.Close();                    
        }                
}
ALTER PROCEDURE [dbo].[InsertAccountFile] 
    @boxID INT,
    @policyNumber VARCHAR(255),
    @fileReference VARCHAR(255),
    @archivedbyID INT,
    @dateArchived SMALLDATETIME,
    @closedPolicy SMALLDATETIME,
    @closedFile SMALLDATETIME,
    @filetypeID INT,
    @comment VARCHAR(255),
    @expectedDestruction SMALLDATETIME,
    @lastupdateID INT,
    @updatedDate SMALLDATETIME,     
    @boxArchiveID INT OUTPUT,
    @returnMessage VARCHAR(255) OUTPUT
AS
BEGIN
    SET NOCOUNT ON

    IF NOT EXISTS(SELECT * FROM BoxArchive WHERE BoxID = @boxID AND FileReference = @fileReference)

    BEGIN
        BEGIN TRY
            INSERT INTO BoxArchive (PolicyNumber, FileReference, ArchivedByID, DateArchived, DatePolicyClosed, ClosedFileDate, BoxID, FileTypeID, Comment, ExpectedDestructionDate, 
                                LastUpdateID, LastUpdateDate) 
            VALUES (@policyNumber, @fileReference, @archivedbyID, @dateArchived, @closedPolicy, @closedFile, @boxID, @filetypeID, @comment, @expectedDestruction,
                                @lastupdateID, @updatedDate)

            SET @returnMessage = 'Success.'
            SET @boxArchiveID = IDENT_CURRENT('BoxArchive') 
        END TRY

        BEGIN CATCH
            SET @returnMessage = ERROR_MESSAGE()
            SET @boxArchiveID = -1
        END CATCH
    END

    ELSE

    BEGIN
        SET @returnMessage = 'Error: "' + @fileReference + '" already exists in this box.' 
        SET @boxArchiveID = -1
    END

userName in debugging is correctly returning my name, also userID knows my ID which in this case is 8. On the server it seems to come back with -1.

Snooley
  • 71
  • 1
  • 11
  • the error you are getting is on insert statement. But, you are saying that the procedure only has a select statement. Are you sure you are not using insert anywhere? – sabhari karthik Apr 11 '19 at 08:03
  • I have a button that does the insert, will edit the code in now – Snooley Apr 11 '19 at 08:05
  • 1
    It seems that the user you are trying to get value from doesn't exist in the database, as the message shows that the value '-1' ..column 'PersonID'.###-1###'... is nonexistent. In the server, you need to be sure that the user that is running the .NET process is the correct one, since your process might be running inside the IIS with another user. And yes, as mentioned above, your error is in a insert statement, would be nice to know how you are inserting this data into your database. – Bruno Apr 11 '19 at 08:05
  • Added my insert code. I can't get my head around why it knows it is me inserting files locally but on the server it doesn't. – Snooley Apr 11 '19 at 08:19
  • `I have tried enabling Windows Authentication in IIS` - have you also disabled anonymous authentication? – GSerg Apr 11 '19 at 08:28
  • are you using HttpContext.Current.User.Identity.Name.Replace(".", " "); in the server for fetching AD identity? If not, try that. Because, AD identity code's usage might vary between localhost and server. – sabhari karthik Apr 11 '19 at 08:29
  • You have a lot of moving parts here. The very first thing you need to do is display the contents of `userName`. That is debugging 101. Please find out what it is and add to your question. You could also disable the FK, let it insert and inspect it in the database. – Nick.Mc Apr 11 '19 at 08:31
  • In IIS Windows Authentication is the only one enabled. As far as I am aware yes, I also have `` in the Web.config. `userName` in debugging is correctly returning my name, also `userID` knows my ID which in this case is 8. On the server it seems to come back with -1. – Snooley Apr 11 '19 at 09:18

3 Answers3

2

Okay so after hours of searching I managed to find a solution that worked for me. In web.config under <system.web>, I already had this code:

<authentication mode="Windows" />
<authorization>
  <allow users="*" />
</authorization>

The bit I seemed to be missing was:

<identity impersonate ="true"/>

Hopefully this can help anyone that finds themselves in this situation!

Link to @gokul answer for more detail here!

Snooley
  • 71
  • 1
  • 11
0

So, the issue seems to be with setting up windows authentication in your server. Check

  1. enabling authentication in IIS
  2. web.config file for authentication mode = 'windows' line

and have a look in https://docs.kentico.com/k10/managing-users/user-registration-and-authentication/configuring-windows-ad-authentication for setting up AD authentication.

Hope this helps you :)

sabhari karthik
  • 1,361
  • 6
  • 17
0

There is something in your code that seems odd

you said that you are getting the username like this:

string userName = Environment.UserName.Replace(".", " ");

But below you are passing its value directly using Environment.UserName like this:

cmd.Parameters.AddWithValue("@userName", Environment.UserName);

Is that really what you meant? Besides, I strongly recommend you to LOG the userID that you are getting in the server, it will make your life easier, you can use Nlog for that.

Bruno
  • 924
  • 9
  • 20
  • Sorry yes you are correct. Although, `Environment.UserName` is what I need passed though. I will have a look at that now thank you! – Snooley Apr 11 '19 at 09:04