NET Core 2 MVC-为GET方法存储对象

时间:2018-11-20 22:13:25

标签: c# api asp.net-core asp.net-core-mvc asp.net-core-2.0

我在索引页面上有一个搜索表单,可以在外部数据库中搜索可用的客房和酒店。提交表单后,用户将被重定向到包含可用酒店列表的新页面(稍后将提供客房)。

提交表单后,将搜索参数放入单个字符串中,然后将其通过ModelManager传递到TcpConnectionManager类,在此该字符串被序列化为json并通过套接字发送到外部Java服务器。服务器反序列化json,将字符串元素放在SQL查询中,然后SQL查询数据库并返回所有可用的hotel对象。然后将这些酒店对象放置在HotelList对象中,序列化为json并通过套接字发送回TcpConnectionManager类。

我最大的问题是在HotelController中实现GET方法。试图将HotelList对象存储在TcpConnectionManager类中,但是GET方法始终返回空对象。

到目前为止,我已经可以通过实现一个单例类TempHotelsStorage来实现我想要的目标,该类具有存储和检索HotelList对象的方法,但是我最大的担心是在这种情况下这是否是一种好/正确的方法?如果没有,那么如何改善呢?

HomeController.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(); 
    }
}
}

HotelController.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();
    }
}

TcpConnectionManager.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;
        }
    }
}
}

TempHotelsStorage.cs:

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>"
                );
        }
    }
});
}

jQuery列出所有酒店:

<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>

HTML标记:

cd c:\Users\LOrdBenche\source\repos\parsingTest\parsingTest\producedJSON

2 个答案:

答案 0 :(得分:2)

您可以省去一些麻烦,并允许依赖项注入来处理服务的寿命。您可以通过声明服务的接口和实现,在id类的ConfigureServices方法中注册服务,例如:
Startup
然后只需将所述服务添加为控制器的构造器参数即可。
同样,您的services.AddTransient<ITcpConnectionManager, TcpConnectionManager>();类在这里似乎有些多余。如果仅在TempHotelsStorage方法中使用return JsonConvert.DeserializeObject<HotelList>(DataReceived);,则可以完全避免使用它。 通常,我也建议不要使用相同的方法来管理连接和检索数据,但这可能超出了此特定问题的范围。

关于使用单例对象-通常在需要在应用程序的整个生命周期中保持对象(例如,保持某些状态)的情况下使用它们。这里不是这种情况。

答案 1 :(得分:0)

按照Marchyello的建议,首先使用依赖项注入在Startup类中注册了单例服务:

flask.cli.NoAppException: While importing "run", an ImportError was raised:

Traceback (most recent call last):
  File "/home/eric/Documents/coding/venv/lib/python3.6/site-packages/flask/cli.py", line 235, in locate_app
    __import__(module_name)
  File "/home/eric/Documents/coding/adminsystem/run.py", line 3, in <module>
    from app import create_app
  File "/home/eric/Documents/coding/adminsystem/app/__init__.py", line 16, in <module>
    from .home.views import check_role
  File "/home/eric/Documents/coding/adminsystem/app/home/__init__.py", line 5, in <module>
    from . import views
  File "/home/eric/Documents/coding/adminsystem/app/home/views.py", line 9, in <module>
    from ..auth.forms import MemberRegistrationForm
  File "/home/eric/Documents/coding/adminsystem/app/auth/__init__.py", line 5, in <module>
    from . import views
  File "/home/eric/Documents/coding/adminsystem/app/auth/views.py", line 4, in <module>
    from ..home.views import check_role
ImportError: cannot import name 'check_role'

然后将单例服务添加为每个控制器的构造函数参数,如下所示:

services.AddSingleton<IModelManager, ModelManager>();

ModelManager类只是模型的基础,它是api控制器通过调用GET和POST方法存储和检索数据的访问点。

HomeController:

    private readonly IModelManager _modelManager;

    public HotelController(IModelManager modelManager)
    {
        _modelManager = modelManager;
    }

HotelController:

    [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");
    }

ModelManager:

    [HttpGet]
    public ActionResult<HotelList> Get()
    {
        return _modelManager.ReturnQuery();
    }

ModelManager是单例的,因为Hotel控制器需要访问Home控制器将查询字符串存储到的ModelManager实例,然后再重定向到Hotel视图。此外,下一步将是基于酒店选择列出可用的房间,并且房间控制器的GET方法将需要访问与酒店控制器相同的HotelList对象。