NET Core 2 MVC - 为 GET 方法存储对象
NET Core 2 MVC - Storing objects for GET method
我的索引页上有一个搜索表单,用于在外部数据库中搜索可用的房间和旅馆。提交表单后,用户将被重定向到一个包含可用酒店列表的新页面(房间稍后会出现)。
提交表单后,搜索参数被放入单个字符串中,然后通过 ModelManager 传递给 TcpConnectionManager class,在此字符串被序列化为 json 并通过到外部 Java 服务器的套接字。服务器反序列化 json,将字符串元素放入 SQL 查询中,后者依次检查数据库和 returns 所有可用的酒店对象。然后将这些酒店对象放置在 HotelList 对象中,序列化为 json 并通过套接字发送回 TcpConnectionManager class。
我最大的问题是在 HotelController 中实现 GET 方法。尝试将 HotelList 对象存储在 TcpConnectionManager class 中,但 GET 方法始终返回空对象。
到目前为止,我已经能够通过实现单例 class TempHotelsStorage 来完成我想要的,它具有存储和检索 HotelList 对象的方法,但我最担心的是这是否是一个 good/right 这种情况下的处理方法?如果不是,那如何改进?
HomeController.cs :
namespace NETCoreWebApp.Controllers
{
public class HomeController : Controller
{
private readonly IModelManager iModelManager = new ModelManager();
public IActionResult Index()
{
return View();
}
public IActionResult Hotel()
{
return View();
}
[HttpPost]
public IActionResult Index(SearchRoomsModel model)
{
string query = string.Format("{0},{1} 12:00,{2} 12:00,{3},{4}", model.Location, model.CheckIn, model.CheckOut, model.NumAdults, model.NumChild);
iModelManager.GetAvailableRooms(query);
return RedirectToAction("Hotel");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
HotelController.cs:
namespace NETCoreWebApp.Controllers
{
[Route("api/hotel")]
[ApiController]
public class HotelController : Controller
{
public TempHotelsStorage hotelsStorage = TempHotelsStorage.Instance;
[HttpGet]
public ActionResult<HotelList> Get()
{
return hotelsStorage.GetHotelsFromStorage();
}
}
}
TcpConnectionManager.cs :
public class TcpConnectionManager
{
public TempHotelsStorage hotelStorage = TempHotelsStorage.Instance;
public void GetAvailableRooms(string query)
{
//Sending json to other server
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("127.0.0.1", 6767);
NetworkStream ns = clientSocket.GetStream();
string jsonRequest = query;
string jsonToSend = JsonConvert.SerializeObject(jsonRequest);
byte[] dataBytes = Encoding.UTF8.GetBytes(jsonToSend);
ns.Write(dataBytes, 0, dataBytes.Length);
//Receiving json from other server
byte[] buffer = new byte[clientSocket.ReceiveBufferSize];
int bytesRead = ns.Read(buffer, 0, clientSocket.ReceiveBufferSize);
string DataReceived = Encoding.UTF8.GetString(buffer, 2, bytesRead);
HotelList hotelList = JsonConvert.DeserializeObject<HotelList>(DataReceived);
hotelStorage.SaveHotels(hotelList);
clientSocket.Close();
ns.Close();
}
}
TempHotelsStorage.cs :
namespace NETCoreWebApp.Models
{
public class TempHotelsStorage
{
private static readonly TempHotelsStorage instance = new TempHotelsStorage();
static TempHotelsStorage() { }
private TempHotelsStorage() { }
public HotelList hotelList { get; set; } = new HotelList();
public void SaveHotels(HotelList hList)
{
for (int i = 0; i < hList.Size(); i++)
{
hotelList.AddHotel(hList.GetHotelByIndex(i));
}
}
public HotelList GetHotelsFromStorage()
{
return hotelList;
}
public static TempHotelsStorage Instance
{
get
{
return instance;
}
}
}
}
jQuery 列出所有酒店:
function getData() {
$.ajax({
type: "GET",
url: uri,
cache: false,
dataType: 'json',
success: function (data) {
const hotelListContainer = $('#hotelListContainer');
for (var i = 0; i < data.hotelList.length; i++)
{
hotelListContainer
.append(
"<div class='col-md-12' id='hotelListItem'>" +
"<div class='col-md-3' id='hotelItemPicture'>ID:" + data.hotelList[i].hid + "</div>" +
"<div class='col-md-9' id='hotelItemDescription'>NAME:" + data.hotelList[i].name + "</div>" +
"</div>"
);
}
}
});
}
HTML 标记:
<div class="container-fluid" id="hotelListArea">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8" id="centerHotelListArea">
<div id="hotelListContainer">
<div id="hotelContainerItem"></div>
</div>
</div>
<div class="col-md-2"></div>
</div>
您可以让自己省去一些麻烦,并允许依赖项注入来处理服务的生命周期。您可以在 Startup
class 的 ConfigureServices
方法中通过声明其接口和实现来注册服务,例如:
services.AddTransient<ITcpConnectionManager, TcpConnectionManager>();
然后只需将所述服务添加为控制器的构造函数参数即可。
此外,您的 TempHotelsStorage
class 在这里似乎有些多余。如果您只在 GetAvailableRooms
方法中使用 return JsonConvert.DeserializeObject<HotelList>(DataReceived);
,则可以完全避免使用它。
一般来说,我也建议不要使用相同的方法管理连接和检索数据,但这可能超出了这个特定问题的重点。
关于使用单例对象 - 您通常会在需要在应用程序的整个生命周期中保留对象的情况下使用它们,例如保留某些状态。这里不是这种情况。
按照 Marchyello 的建议,使用依赖注入,我首先在 Startup class:
中注册了单例服务
services.AddSingleton<IModelManager, ModelManager>();
然后像这样为每个控制器添加单例服务作为构造函数参数:
private readonly IModelManager _modelManager;
public HotelController(IModelManager modelManager)
{
_modelManager = modelManager;
}
ModelManager class,它只是模型的外观,充当 api 控制器的访问点,通过调用 GET 和 POST 方法存储和检索数据.
家庭控制器:
[HttpPost]
public IActionResult Index(SearchRoomsModel model)
{
string _query = string.Format("{0},{1} 12:00,{2} 12:00,{3},{4}", model.Location, model.CheckIn, model.CheckOut, model.NumAdults, model.NumChild);
_modelManager.SaveQuery(_query);
return RedirectToAction("Hotel");
}
酒店管理员:
[HttpGet]
public ActionResult<HotelList> Get()
{
return _modelManager.ReturnQuery();
}
模型管理器:
private readonly TcpConnectionManager _tcpManager = new TcpConnectionManager();
public string _query;
public void SaveQuery(string query)
{
_query = query;
}
public HotelList ReturnQuery()
{
HotelList hotelList = _tcpManager.ReturnHotelList(_query);
return hotelList;
}
ModelManager 是一个单例,因为酒店控制器需要访问 Home 控制器在重定向到酒店视图之前将查询字符串存储到的同一 ModelManager 实例。此外,下一步将根据酒店选择列出可用房间,房间控制器的 GET 方法将需要访问与酒店控制器相同的 HotelList 对象。
我的索引页上有一个搜索表单,用于在外部数据库中搜索可用的房间和旅馆。提交表单后,用户将被重定向到一个包含可用酒店列表的新页面(房间稍后会出现)。
提交表单后,搜索参数被放入单个字符串中,然后通过 ModelManager 传递给 TcpConnectionManager class,在此字符串被序列化为 json 并通过到外部 Java 服务器的套接字。服务器反序列化 json,将字符串元素放入 SQL 查询中,后者依次检查数据库和 returns 所有可用的酒店对象。然后将这些酒店对象放置在 HotelList 对象中,序列化为 json 并通过套接字发送回 TcpConnectionManager class。
我最大的问题是在 HotelController 中实现 GET 方法。尝试将 HotelList 对象存储在 TcpConnectionManager class 中,但 GET 方法始终返回空对象。
到目前为止,我已经能够通过实现单例 class TempHotelsStorage 来完成我想要的,它具有存储和检索 HotelList 对象的方法,但我最担心的是这是否是一个 good/right 这种情况下的处理方法?如果不是,那如何改进?
HomeController.cs :
namespace NETCoreWebApp.Controllers
{
public class HomeController : Controller
{
private readonly IModelManager iModelManager = new ModelManager();
public IActionResult Index()
{
return View();
}
public IActionResult Hotel()
{
return View();
}
[HttpPost]
public IActionResult Index(SearchRoomsModel model)
{
string query = string.Format("{0},{1} 12:00,{2} 12:00,{3},{4}", model.Location, model.CheckIn, model.CheckOut, model.NumAdults, model.NumChild);
iModelManager.GetAvailableRooms(query);
return RedirectToAction("Hotel");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
HotelController.cs:
namespace NETCoreWebApp.Controllers
{
[Route("api/hotel")]
[ApiController]
public class HotelController : Controller
{
public TempHotelsStorage hotelsStorage = TempHotelsStorage.Instance;
[HttpGet]
public ActionResult<HotelList> Get()
{
return hotelsStorage.GetHotelsFromStorage();
}
}
}
TcpConnectionManager.cs :
public class TcpConnectionManager
{
public TempHotelsStorage hotelStorage = TempHotelsStorage.Instance;
public void GetAvailableRooms(string query)
{
//Sending json to other server
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("127.0.0.1", 6767);
NetworkStream ns = clientSocket.GetStream();
string jsonRequest = query;
string jsonToSend = JsonConvert.SerializeObject(jsonRequest);
byte[] dataBytes = Encoding.UTF8.GetBytes(jsonToSend);
ns.Write(dataBytes, 0, dataBytes.Length);
//Receiving json from other server
byte[] buffer = new byte[clientSocket.ReceiveBufferSize];
int bytesRead = ns.Read(buffer, 0, clientSocket.ReceiveBufferSize);
string DataReceived = Encoding.UTF8.GetString(buffer, 2, bytesRead);
HotelList hotelList = JsonConvert.DeserializeObject<HotelList>(DataReceived);
hotelStorage.SaveHotels(hotelList);
clientSocket.Close();
ns.Close();
}
}
TempHotelsStorage.cs :
namespace NETCoreWebApp.Models
{
public class TempHotelsStorage
{
private static readonly TempHotelsStorage instance = new TempHotelsStorage();
static TempHotelsStorage() { }
private TempHotelsStorage() { }
public HotelList hotelList { get; set; } = new HotelList();
public void SaveHotels(HotelList hList)
{
for (int i = 0; i < hList.Size(); i++)
{
hotelList.AddHotel(hList.GetHotelByIndex(i));
}
}
public HotelList GetHotelsFromStorage()
{
return hotelList;
}
public static TempHotelsStorage Instance
{
get
{
return instance;
}
}
}
}
jQuery 列出所有酒店:
function getData() {
$.ajax({
type: "GET",
url: uri,
cache: false,
dataType: 'json',
success: function (data) {
const hotelListContainer = $('#hotelListContainer');
for (var i = 0; i < data.hotelList.length; i++)
{
hotelListContainer
.append(
"<div class='col-md-12' id='hotelListItem'>" +
"<div class='col-md-3' id='hotelItemPicture'>ID:" + data.hotelList[i].hid + "</div>" +
"<div class='col-md-9' id='hotelItemDescription'>NAME:" + data.hotelList[i].name + "</div>" +
"</div>"
);
}
}
});
}
HTML 标记:
<div class="container-fluid" id="hotelListArea">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8" id="centerHotelListArea">
<div id="hotelListContainer">
<div id="hotelContainerItem"></div>
</div>
</div>
<div class="col-md-2"></div>
</div>
您可以让自己省去一些麻烦,并允许依赖项注入来处理服务的生命周期。您可以在 Startup
class 的 ConfigureServices
方法中通过声明其接口和实现来注册服务,例如:
services.AddTransient<ITcpConnectionManager, TcpConnectionManager>();
然后只需将所述服务添加为控制器的构造函数参数即可。
此外,您的 TempHotelsStorage
class 在这里似乎有些多余。如果您只在 GetAvailableRooms
方法中使用 return JsonConvert.DeserializeObject<HotelList>(DataReceived);
,则可以完全避免使用它。
一般来说,我也建议不要使用相同的方法管理连接和检索数据,但这可能超出了这个特定问题的重点。
关于使用单例对象 - 您通常会在需要在应用程序的整个生命周期中保留对象的情况下使用它们,例如保留某些状态。这里不是这种情况。
按照 Marchyello 的建议,使用依赖注入,我首先在 Startup class:
中注册了单例服务services.AddSingleton<IModelManager, ModelManager>();
然后像这样为每个控制器添加单例服务作为构造函数参数:
private readonly IModelManager _modelManager;
public HotelController(IModelManager modelManager)
{
_modelManager = modelManager;
}
ModelManager class,它只是模型的外观,充当 api 控制器的访问点,通过调用 GET 和 POST 方法存储和检索数据.
家庭控制器:
[HttpPost]
public IActionResult Index(SearchRoomsModel model)
{
string _query = string.Format("{0},{1} 12:00,{2} 12:00,{3},{4}", model.Location, model.CheckIn, model.CheckOut, model.NumAdults, model.NumChild);
_modelManager.SaveQuery(_query);
return RedirectToAction("Hotel");
}
酒店管理员:
[HttpGet]
public ActionResult<HotelList> Get()
{
return _modelManager.ReturnQuery();
}
模型管理器:
private readonly TcpConnectionManager _tcpManager = new TcpConnectionManager();
public string _query;
public void SaveQuery(string query)
{
_query = query;
}
public HotelList ReturnQuery()
{
HotelList hotelList = _tcpManager.ReturnHotelList(_query);
return hotelList;
}
ModelManager 是一个单例,因为酒店控制器需要访问 Home 控制器在重定向到酒店视图之前将查询字符串存储到的同一 ModelManager 实例。此外,下一步将根据酒店选择列出可用房间,房间控制器的 GET 方法将需要访问与酒店控制器相同的 HotelList 对象。