如何在 .NET Maui 中连接到 Azure Web 应用的另一个对象列表中创建连接到 Azure Web 应用的对象列表?

How do I create a list of objects that are connected to an Azure webapp within another list of objects connected to an Azure Webapp in .NET Maui?

提问人:K_Ketchup 提问时间:11/1/2023 最后编辑:K_Ketchup 更新时间:11/2/2023 访问量:40

问:

对不起,标题令人困惑。我不确定如何准确地表达我想要的东西,但我会尽力而为。我目前正在制作一个应用程序,该应用程序使用用户输入的图钉(Restroom.cs 模型)填充地图,每个图钉都有自己的用户输入评论列表。所有内容都是通过访问我的 Azure WebApp 的 WebAPI 输入的。评论和图钉工作正常 - 问题是每个图钉上都显示相同的评论。我知道我需要隔离某种方法来确保每个引脚都有自己的“查看列表”,但我不太确定如何执行此操作或从哪里开始,因为我在使用 Azure 和 WebAPI 进行编程方面非常陌生。我想我必须在 Restroom.cs 中创建一个 ObservableRangeCollection 属性来存储评论,但我不确定从那里去哪里,我还担心有些事情可能需要调整,因为评论将显示在另一个不是主页的页面上。

洗手间.cs

using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SQLite;

namespace Dook.Shared.Models
{
    public class Restroom
    {
        [PrimaryKey, AutoIncrement]
        [Column("Id")]
        public int Id { get; set; }
        [Column("Name")]
        public string Name { get; set; }
        [Column("Address")]
        public string Address { get; set; }
        [Column("Username")]
        public string Username { get; set; }
        [Column("Latitude")]
        public double Latitude { get; set; }
        [Column("Longitude")]
        public double Longitude { get; set; }
    }
}

评论.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SQLite;

namespace Dook.Shared.Models
{
    public class Review
    {
        [SQLite.PrimaryKey, SQLite.AutoIncrement]
        [Column("Id")]
        public int Id { get; set; }
        [Column("Username")]
        public string Username { get; set; }
        [Column("Stars")]
        public double Stars { get; set; }
        [Column("Text")]
        public string Text { get; set; }
        //[Column("Tags")]
        //public string Tags { get; set; }
    }
}

洗手间控制器 .cs

using Microsoft.AspNetCore.Mvc;
using Dook.Shared.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Dook.WebAPI.Controllers
{
    [ApiController]
    [Route("api/Restroom")]
    public class RestroomController : ControllerBase
    {
        public static List<Restroom> Restroom { get; } = new List<Restroom>();

        [HttpGet]
        public IEnumerable<Restroom> Get()
        {
            return Restroom;
        }

        [HttpGet("{id}")]
        public Restroom Get(int id)
        {
            return Restroom.FirstOrDefault(c => c.Id == id);
        }

        [HttpGet("{restId}")]
        public IEnumerable<Restroom> GetList(int restId)
        {
            List<Restroom> RestroomWithID = new List<Restroom>();

            foreach (Restroom rest in Restroom)
            {
                if (rest.RestroomId == restId)
                    RestroomWithID.Add(rest);
            }

            return RestroomWithID;
        }

        [HttpPost]
        public void Post([FromBody] Restroom value)
        {
            Restroom.Add(value);
        }

        [HttpPut("{id}")]
        public void Put(int id, [FromBody] Restroom value)
        {
            var restroom = Restroom.FirstOrDefault(c => c.Id == id);
            if (restroom == null)
                return;

            restroom = value;
        }

        [HttpDelete("{id}")]
        public void Delete(int id)
        {
            var restroom = Restroom.FirstOrDefault(c => c.Id == id);
            if (restroom == null)
                return;

            Restroom.Remove(restroom);
        }
    }
}

ReviewController(评论控制器)

using Microsoft.AspNetCore.Mvc;
using Dook.Shared.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Dook.WebAPI.Controllers
{
    [ApiController]
    [Route("api/Review")]
    public class ReviewController : ControllerBase
    {
        public static List<Review> ReviewList { get; } = new List<Review>();

        [HttpGet]
        public IEnumerable<Review> Get()
        {
            return ReviewList;
        }

        [HttpGet("{id}")]
        public Review Get(int id, int x)
        {
            return ReviewList.FirstOrDefault(c => c.Id == id);
        }

        [HttpGet("{restId}")]
        public IEnumerable<Review> GetWithRestroomID(int restId)
        {
            List<Review> ReviewWithID = new List<Review>();

            foreach(Review rev in ReviewList)
            {
                if(rev.RestroomId == restId)
                    ReviewWithID.Add(rev);
            }

            return ReviewWithID;
        }

        [HttpPost]
        public void Post([FromBody] Review value)
        {
            ReviewList.Add(value);
        }

        [HttpPut("{id}")]
        public void Put(int id, [FromBody] Review value)
        {
            var review = ReviewList.FirstOrDefault(c => c.Id == id);
            if (review == null)
                return;

            review = value;
        }

        [HttpDelete("{id}")]
        public void Delete(int id)
        {
            var review = ReviewList.FirstOrDefault(c => c.Id == id);
            if (review == null)
                return;

            ReviewList.Remove(review);
        }
    }
}

互联网洗手间服务.cs

using Dook.Shared.Models;
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Dook.Services
{
    public static class InternetRestroomService
    {
        //static string Baseurl = DeviceInfo.Platform == DevicePlatform.Android ?
        //                                    "http://10.0.2.2:5000" : "http://localhost:5000";
        static string BaseUrl = "https://dookwebapp.azurewebsites.net/";
        static HttpClient client;

        static InternetRestroomService()
        {
            client = new HttpClient()
            {
                BaseAddress = new Uri(BaseUrl)
            };
        }

        static Random random = new Random();

        public static async Task AddPinAsync(string name, string address, string username, double latitude, double longitude)
        {
            //Check to see if ID is a duplicate
            int idNum = random.Next(0, 100000);
            var randomRestroom = await client.GetStringAsync($"api/Restroom/{idNum}");
            Debug.Write(randomRestroom);

            while (randomRestroom != "")
            {
                idNum = random.Next(0, 100000);
                randomRestroom = await client.GetStringAsync($"api/Restroom/{idNum}");
            }

            var restroom = new Restroom
            {
                Name = name,
                Address = address,
                Username = username,
                Latitude = latitude,
                Longitude = longitude,
                Id = idNum
            };

            var json = JsonConvert.SerializeObject(restroom);
            var content =
                new StringContent(json, Encoding.UTF8, "application/json");

            var response = await client.PostAsync("api/Restroom", content);

            if(!response.IsSuccessStatusCode)
            {

            }
        }

        public static async Task RemovePinAsync(int id)
        {
            var response = await client.DeleteAsync($"api/Restroom/{id}");
            if (!response.IsSuccessStatusCode)
            {

            }
        }

        public static async Task<IEnumerable<Restroom>> GetPinAsync()
        {
            var json = await client.GetStringAsync("api/Restroom");
            var restrooms = JsonConvert.DeserializeObject<IEnumerable<Restroom>>(json);
            return restrooms;
        }

        public static async Task<Restroom> GetSingularPinAsync(int id)
        {
            var json = await client.GetStringAsync($"api/Restroom/{id}");
            var restroom = JsonConvert.DeserializeObject<Restroom>(json);
            return restroom;
        }
    }
}

互联网评论服务.cs

using Dook.Shared.Models;
using Newtonsoft.Json;
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dook.Services
{
    public static class InternetReviewService
    {
        //static string Baseurl = DeviceInfo.Platform == DevicePlatform.Android ?
        //                                    "http://10.0.2.2:5000" : "http://localhost:5000";
        static string BaseUrl = "https://dookwebapp.azurewebsites.net/";
        static HttpClient client;

        static InternetReviewService()
        {
            client = new HttpClient()
            {
                BaseAddress = new Uri(BaseUrl)
            };
        }

        static Random random = new Random();

        public static async Task AddReviewAsync(string username, double stars, string text, int restroomid)
        {
            //Check to see if ID is a duplicate
            int idNum = random.Next(0, 100000);
            var randomReview = await client.GetStringAsync($"api/Restroom/{idNum}");

            while (randomReview != "")
            {
                idNum = random.Next(0, 100000);
                randomReview = await client.GetStringAsync($"api/Restroom/{idNum}");
            }

            var review = new Review()
            {
                Username = username,
                Stars = stars,
                Text = text,
                Id = idNum,
                RestroomId = restroomid 
            };

            var json = JsonConvert.SerializeObject(review);
            var content =
                new StringContent(json, Encoding.UTF8, "application/json");

            var response = await client.PostAsync("api/Restroom", content);

            if (!response.IsSuccessStatusCode)
            {

            }
        }

        public static async Task RemoveReviewAsync(int id)
        {
            var response = await client.DeleteAsync($"api/Restroom/{id}");
            if (!response.IsSuccessStatusCode)
            {

            }
        }

        public static async Task<IEnumerable<Review>> GetReviewAsync(int restId)
        {
            //var json = await client.GetStringAsync($"api/Restroom/{restId}");
            var json = await client.GetStringAsync($"api/Restroom", restId);

            try
            {
                var reviews = JsonConvert.DeserializeObject<IEnumerable<Review>>(json);
                return reviews;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString);
            }

            var review2 = JsonConvert.DeserializeObject<IEnumerable<Review>>(json);
            return review2;
        }
    }
}

MainPage.xaml.cs

namespace Dook;
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using System.Diagnostics;
using Map = Microsoft.Maui.Controls.Maps.Map;
using Dook.ViewModel;
using Dook.Shared.Models;
using Dook.Services;
using CommunityToolkit.Maui.Behaviors;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        MoveMapLocation();
        PopulateMapAsync();
    }

    private void GoToLocation_Button(object sender, EventArgs e)
    {
        MoveMapLocation();
    }

    private async void RefreshButton_Clicked(object sender, EventArgs e)
    {
        await PopulateMapAsync();
    }

    private async void OnMapClicked(object sender, MapClickedEventArgs e)
    {
        var vm = (InternetMainViewModel)this.BindingContext;
        if (vm.AddCommand.CanExecute(e.Location))
            await vm.AddCommand.ExecuteAsync(e.Location);
        await PopulateMapAsync();
    }

    private void MoveMapLocation()
    {
        MapSpan mapSpan = new MapSpan(InternetMainViewModel.GetLocation(), 0.01, 0.01);
        mainmap.MoveToRegion(mapSpan);
    }

    private async Task PopulateMapAsync()
    {
        var restroomList = await InternetRestroomService.GetPinAsync();
        foreach (var restroom in restroomList)
        {
            Pin pin = new Pin
            {
                Label = restroom.Name,
                Address = restroom.Address,
                Type = PinType.Generic,
                Location = new Location(restroom.Latitude, restroom.Longitude)
            };
            pin.MarkerClicked += async (s, args) =>
            {
                args.HideInfoWindow = true;

                var vm = (InternetMainViewModel)this.BindingContext;
                Debug.Write(restroom.Id);
                if (vm.SelectedCommand.CanExecute(restroom))
                    await vm.SelectedCommand.ExecuteAsync(restroom);

                //mainmap.Pins.Remove(pin);
                //if(vm.RemoveCommand.CanExecute(restroom))
                //    await vm.RemoveCommand.ExecuteAsync(restroom);
                //await PopulateMapAsync();
            };

            mainmap.Pins.Add(pin);
        }
    }
}

RestroomDetailPage.xaml.cs

using Dook.Services;
using Dook.Shared.Models;
using Dook.ViewModel;
using System.Windows.Input;

namespace Dook.View;

[QueryProperty(nameof(RestroomId), nameof(RestroomId))]
public partial class RestroomDetailPage : ContentPage
{
    public string RestroomId { get; set; }
    public Restroom restroom { get; set; }
    public RestroomDetailPage()
    {
        InitializeComponent();

        var vm = (InternetRestroomDetailViewModel)this.BindingContext;
        ToolbarItem item = new ToolbarItem
        {
            Text = "Add"
        };
        item.Clicked += async (s, args) =>
        {
            if (vm.AddCommand.CanExecute(restroom.Id.ToString()))
                await vm.AddCommand.ExecuteAsync(restroom.Id.ToString());
        };
        this.ToolbarItems.Add(item);

        ICommand refreshCommand = new Command(() =>
        {
            if (vm.RefreshCommand.CanExecute(restroom.Id.ToString()))
                vm.RefreshCommand.ExecuteAsync(restroom.Id.ToString());
            
        });
        ReviewList.RefreshCommand = refreshCommand;
    }

    protected override async void OnAppearing()
    {
        base.OnAppearing();
        int.TryParse(RestroomId, out var result);

        restroom = await InternetRestroomService.GetSingularPinAsync(result);
        BindingContext = restroom;
    }

  //  private async void Button_Clicked(object sender, EventArgs e)
  //  {
        //await Shell.Current.GoToAsync("..");
  //  }
}

互联网洗手间详细信息视图模型.cs

using Dook.Shared.Models;
using Newtonsoft.Json;
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dook.Services
{
    public static class InternetReviewService
    {
        //static string Baseurl = DeviceInfo.Platform == DevicePlatform.Android ?
        //                                    "http://10.0.2.2:5000" : "http://localhost:5000";
        static string BaseUrl = "https://dookwebapp.azurewebsites.net/";
        static HttpClient client;

        static InternetReviewService()
        {
            client = new HttpClient()
            {
                BaseAddress = new Uri(BaseUrl)
            };
        }

        static Random random = new Random();

        public static async Task AddReviewAsync(string username, double stars, string text, int restroomid)
        {
            //Check to see if ID is a duplicate
            int idNum = random.Next(0, 100000);
            var randomReview = await client.GetStringAsync($"api/Restroom/{idNum}");

            while (randomReview != "")
            {
                idNum = random.Next(0, 100000);
                randomReview = await client.GetStringAsync($"api/Restroom/{idNum}");
            }

            var review = new Review()
            {
                Username = username,
                Stars = stars,
                Text = text,
                Id = idNum,
                RestroomId = restroomid 
            };

            var json = JsonConvert.SerializeObject(review);
            var content =
                new StringContent(json, Encoding.UTF8, "application/json");

            var response = await client.PostAsync("api/Restroom", content);

            if (!response.IsSuccessStatusCode)
            {

            }
        }

        public static async Task RemoveReviewAsync(int id)
        {
            var response = await client.DeleteAsync($"api/Restroom/{id}");
            if (!response.IsSuccessStatusCode)
            {

            }
        }

        public static async Task<IEnumerable<Review>> GetReviewAsync(int restId)
        {
            //var json = await client.GetStringAsync($"api/Restroom/{restId}");
            var json = await client.GetStringAsync($"api/Restroom/{restId}");
            var reviews = JsonConvert.DeserializeObject<IEnumerable<Review>>(json);
            return reviews;
        }
    }
}
C# asp.net .NET Xamarin Maui

评论

0赞 jdweng 11/1/2023
你有一个数据库。引脚是数据库中的一个表,也是 c# 代码中的一个类。评论是不同的表/类。每个 Pin 图都需要一个 ID(属性/字段),该 ID 与包含相同 ID 的评价表联接。
0赞 K_Ketchup 11/1/2023
明白了。这是有道理的。我甚至要确保在图钉中进行的每条评论都具有与图钉相同的“PinID”(与“ReviewID”分开),但我不确定如何使 RestroomDetailPage 列表视图仅显示具有相同“PinID”的评论。你会怎么做?
0赞 Jason 11/1/2023
GetReviewAsync 应接受 PinID 作为参数,并仅检索匹配的评价
0赞 jdweng 11/1/2023
应将以下代码行更改为仅获取 ID 的审核:var json = await client。GetStringAsync(“api/Restroom”);
0赞 K_Ketchup 11/2/2023
我尝试实现这些更改,但我似乎无法关闭 GetReviewAsync 方法——json 始终包含一个 Restroom 对象,而不是 Restroom 对象列表。我还尝试更改 RestroomController 和 ReviewController 以包含 GetList 方法,但我不确定如何在 GetReviewAsync 方法中调用它。另外,我不确定我是否应该在 InternetReviewService 中调用 api/Restroom(它之前在评论中工作过),所以这也可能是一个问题。该帖子已更新,包括我所做的所有更改。

答: 暂无答案