ASP.NET MVC RedirectToAction не перенаправит меня на новый идентификатор

#asp.net-mvc

#asp.net-mvc

Вопрос:

У меня есть приложение, в котором вы можете создать пользователя с именем и электронной почтой. Когда пользователь создается, он добавляется в базу данных и ему присваивается идентификатор (первичный ключ).

Когда я создаю пользователя, функция RedirectToAction не перенаправляет меня на домашнюю страницу нового пользователя, но по-прежнему перенаправляет меня к пользователю, который создал пользователя, хотя я говорю контроллеру перенаправить меня на домашнюю страницу пользователя недавно созданного идентификатора.

     return RedirectToAction("GetUser", "User", new { id = userAdd.ID })
 

Учетная запись пользователя создается, поскольку я вижу ее в базе данных и списке пользователей, поэтому функция AddUser работает, просто кажется, что эта строка кода не работает.

Я инициализирую приложение в первый профиль пользователя ID (1), который затем может создать другого пользователя.

Может кто-нибудь сказать мне, что здесь пошло не так?

Файл Routeconfig.cs, указывающий на первый идентификатор пользователя в качестве инициализации:

             routes.MapRoute(
            name: "User",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "User", action = "GetUser", ID = 1 }
            );

 

Контроллер, который добавляет пользователя:

             public ActionResult AddUser(UserAdd userAdd)
        {
            try
            {
                // TODO: Add insert logic here
                userService.AddUser(userAdd);
                return RedirectToAction("GetUser", "User", new { id = userAdd.ID });
            }
            catch
            {
                return View();
            }
        }
 

Мой пользователь DAO и IDAO следуют.

DAO :

     public void AddUser(User user, TheContext context)
    {
        context.Users.Add(user);
        context.SaveChanges();
    }
 

IDAO:

 
    void AddUser(User user, TheContext context);
 

Мой код уровня пользовательского сервиса:

Обслуживание:

     public void AddUser(UserAdd userAdd)
    {
        User newUser = new User()
        {
            Name = userAdd.Name,
            Email = userAdd.Email
        };

        using (var context = new TheContext())
        {
            userDAO.AddUser(newUser, context);
        }
    }
 

IService:

      void AddUser(UserAdd userAdd);
 

GetUser action:
DAO:

 public User GetUser(int id, TheContext context)
    {
        context.Users.Include(h => h.UserDetails).ToList();
        return context.Users.Find(id);
    }
 

IDAO:

  User GetUser(int id, TheContext context);
 

Service:

         public User GetUser(int id)
    {
        using (var context = new TheContext())
        {
            return userDAO.GetUser(id, context);
        }
    }
 

IService:

 User GetUser(int id);
 

Controller:

         public ActionResult GetUser(int id)
    {
        return View(userService.GetUser(id));
    }
 

GetUser.cshtml view:

     @model Tester.Data.Models.Domain.User

@{
    ViewBag.Title = "GetUser";
}

<h2>My Test App</h2>

<div>
    <p>@Html.ActionLink("Register", "AddUser", "User")</p>

</div>
    <h2>Details for @Model.Name</h2>
@if (Model.UserDetails.Count != 0)
{
    @Html.Partial("~/Views/User/GetUserDetails.cshtml", Model.UserDetails);
}
 

Initaliser class:

 protected override void Seed(TheContext context)
{
    User user1 = new User();
    user1.ID = "1";
    user1.Name = "test";
    user1.Email = "test@test.com";
    context.Users.Add(user1);

    UserDetail userDetail1 = new UserDetail();
    userDetail1.Name = "test";
    userDetail1.Email = "test.com";
    context.UserDetails.Add(userDetail1);

    context.SaveChanges();
 

Однако я мог бы использовать:

 TheContext.Data.Models.Domain.User user = new TheContext.Data.Models.Domain.User();
user.Name = "test";
user.Email = "test@test.com";

TheContext.Data.Models.Domain.UserDetail userDetail = new TheContext.Data.Models.Domain.UserDetail();
userDetail.Name = "test";
userDetail.Email = "test@test.com";
 

T-SQL для пользователей:

 CREATE TABLE [dbo].[Users] (
    [ID]    INT            IDENTITY (1, 1) NOT NULL,
    [Name]  NVARCHAR (MAX) NULL,
    [Email] NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([ID] ASC)
);
 

T-SQL для пользовательских данных:

 CREATE TABLE [dbo].[UserDetails] (
    [ID]            INT            IDENTITY (1, 1) NOT NULL,
    [Name]          NVARCHAR (MAX) NULL,
    [Email]         NVARCHAR (MAX) NULL,
    [User_ID]       INT            NULL,
    CONSTRAINT [PK_dbo.UserDetails] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_dbo.UserDetails_dbo.Users_User_ID] FOREIGN KEY ([User_ID]) REFERENCES [dbo].[Users] ([ID])
);
 

Класс пользователя:

     public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public virtual ICollection<UserDetail> UserDetails { get; set; }
}
 

Класс UserDetails:

 public class UserDetail
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}
 

Комментарии:

1. знаете ли вы, если в ответ RedirectToAction(«getUser», «User», new { id = userAdd. Строка ID }), ваш userAdd. Идентификатор имеет допустимое значение? Насколько я вижу, он никогда не назначался. Вы только присвоили значения из него свойствам другого экземпляра. Попробуйте вернуть идентификатор из void AddUser(UserAdd userAdd); в IService и используйте его в своем контроллере. Код RedirectToAction мне нравится.

2. @Dave я не уверен, есть ли способ проверить, присвоено ли ему значение? Что касается IService amp; Service, я реализовал void AddUser(UserAdd userAdd, идентификатор int). Для контроллера я отредактировал actionresult в (UserAdd userAdd, int ID), и я возвращаю значение ID (UserService . AddUser(userAdd, ID)). Эти изменения, к сожалению, не сработали, поэтому у меня такое чувство, что вы правы, идентификатору не присваивается значение. Не могли бы вы объяснить подробнее, пожалуйста? Я заглянул в базу данных, и созданному мной пользователю присваивается значение ID, поскольку оно является первичным ключом в таблице.

3. Вы можете установить точку останова при return RedirectToAction("GetUser", "User", new { id = userAdd.ID }) вызове и посмотреть, имеет ли после добавления пользователя userAdd.ID новое значение идентификатора. Если там нет значения, вам нужно обновить IService.void AddUser(UserAdd userAdd); его, чтобы вернуть int/string вместо void . Объявите переменную в этом методе, после создания пользователя назначьте эту переменную из newUser экземпляра и верните ее контроллеру. Чем в RedirectToAction call, используйте возвращаемое значение в качестве идентификатора. Я не могу отформатировать код здесь, поэтому, к сожалению, я не могу опубликовать его здесь.

4. @Dave Спасибо, что сказали мне. Итак, я вижу, что userAdd. Присвоенный идентификатор равен 1, поэтому он переводит меня на страницу идентификатора 1. Знаете ли вы, почему ему присваивается значение 1, когда у меня есть идентификатор в качестве первичного ключа, и потому, что когда я заглядываю в базу данных, присваивается значение идентификатора 2.

5. может быть, когда вы вошли в систему с идентификатором пользователя 1, он передается и сохраняется в viewmodel. поэтому, когда вы отправляете запрос, идентификатор 1, сохраненный в этой viewmodel, также передается обратно контроллеру, который позже никогда не обновлялся. Как я предлагал ранее, из вашей службы верните новый идентификатор и используйте его вместо этого.

Ответ №1:

Вместо того, чтобы использовать ID модель из опубликованного представления, получите ID вновь созданную запись из сервиса и используйте ее.

IService:
int AddUser(UserAdd userAdd);

Обслуживание:

 public int AddUser(UserAdd userAdd)
{
   var userId = 0;
   User newUser = new User()
   {
       Name = userAdd.Name,
       Email = userAdd.Email
   };

   using (var context = new TheContext())
   {
       userDAO.AddUser(newUser, context);
       // assing Id here after add
       userId = newUser.ID;
   }
   return userId;
}
 

Метод действия:

 public ActionResult AddUser(UserAdd userAdd)
{
   try
   {
     // capture Id from service
     var newId = userService.AddUser(userAdd);
     return RedirectToAction("GetUser", "User", new { id = newId });
   }
   catch
   {
     return View(userAdd);   // return view with posted model so you don't loose data
   }
}
 

Комментарии:

1. @Sergey я прочитал ваш ответ. это не решает проблему. В вашем предлагаемом return GetUser(userAdd.ID ) идентификаторе вызова всегда 1, поэтому OP снова видит ту же страницу. Исходя из того, что описал OP, RedirectToAction() не является проблемой. Вы просто написали то же самое по-другому. Здесь нам нужно получить обновленный идентификатор для вновь добавленной записи.

2. ваша строка AddUser(UserAdd userAdd) возвращает строку, но идентификатор должен быть int . И весь ваш код AddUser не делает ничего нового, только добавляет ошибку. И ошибкой является использование перенаправления вместо простого вызова действия.

3.@Sergey я опубликовал ответ, когда не знал о типе данных, поэтому в коде есть комментарий: // assuming primary key is of type string я не вижу никакой разницы в результате со следующим, когда Id равен 1. return GetUser(userAdd.ID) return RedirectToAction("GetUser", "User", new { id = newId }); Они оба в конечном итоге извлекают одного и того же пользователя из базы данных. Как это решило проблему? Если вы прочитали второй абзац, о котором идет речь, проблема не в том, что перенаправление вообще не работает. Он снова перенаправляется тому же пользователю. OP необходимо перенаправить на нового пользователя.

4. Я только что изменил свой тип данных первичного ключа на string, изначально он был int id, но теперь является string id. Я использовал ваш код и получаю сообщение об ошибке в UserService: «‘UserService. AddUser(UserAdd)’: не все пути кода возвращают значение «. Если это поможет, я использую класс для инициализации первого пользователя и некоторых деталей, у меня есть 2 варианта, не могли бы вы предложить, какой из них будет более подходящим или если они по сути одинаковы. Я отредактировал сообщение с подробностями

5. @DAVID извините, это была опечатка. метод должен возвращать идентификатор пользователя в конце. обновил мой ответ. Вам не нужно изменять тип данных PK. Если вы это сделали, убедитесь, что метод AddUser() в service возвращает тот же тип данных.