#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 возвращает тот же тип данных.