通过使用EntityFramework传递非PK值来获取PK值

时间:2015-04-03 19:46:00

标签: c# sql-server entity-framework asp.net-web-api2

我正在构建一个使用Web API和Entity Framework连接到SQL数据库的Windows Phone 8.1应用程序。在我当前的设置中,我的服务项目中包含我的实体的数据对象(包含PK id属性)和我的手机客户端项目中的模型(不包含PK id属性,以便在启用时自动增加新成员已创建。我正在尝试编写一个服务方法,当用户名传递给它时返回memberID值(成员实体的PK)。但是,当我这样做时,我收到以下错误:

System.InvalidCastException:无法将类型为“System.Net.Http.StreamContent”的对象强制转换为“System.IConvertible”。

我不确定我是否正在尝试做一些不起作用的事情,或者是否有更简单的方法来做到这一点,但我的代码构建成功。上述错误是运行时错误。这是我用于相关课程的代码:

这是从我的客户端的后端调用我的服务器的方法:

public async void GetMembers(String currUser, String currPass)
    {
        using (var client = new HttpClient())
        {
            //MembersListBox.Items.Add("using block entered");
            client.BaseAddress = new Uri("http://nflff.azurewebsites.net");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            //MembersListBox.Items.Add("client's defaultrequestheaders done");

            //gets all members from table
            HttpResponseMessage response = await client.GetAsync("api/Members");
            //MembersListBox.Items.Add("after response reached");
            if (response.IsSuccessStatusCode)
            {
                //reads all member objs from table as a json string
                string s = await response.Content.ReadAsStringAsync();
                //how can we pass the user's login credentials (including ID) to other pages? via HttpClient?
                //converts string of members into a list of member objs
                var deserializedResponse = JsonConvert.DeserializeObject<List<Members>>(s);
                foreach (Members member in deserializedResponse)
                {
                    //if current member matches a member found in list
                    if(member.compareUserAndPassword(currUser, currPass)) {
                        MembersListBox.Items.Add(currUser + " and " + currPass + " found.");
                        MembersListBox.Items.Add(member.userName + " " + member.password);
                        Members currMember = member; //this works
                        MembersListBox.Items.Add("Current member: " + currMember.ToString());
                        //how should memberID be remembered for user?
                        client.DefaultRequestHeaders.Authorization = CreateBasicHeader(currUser, currPass);
                        MembersListBox.Items.Add(client.DefaultRequestHeaders.Authorization);
                        HttpResponseMessage memResponse = await client.GetAsync("api/Members/" + currUser);
                        if (memResponse.IsSuccessStatusCode)
                        {
                            MembersListBox.Items.Add("memResponse successful");
                        }
                        //should only go to home page if successful
                        //int memID = Convert.ToInt32(await client.GetAsync("api/Members?MemberStr=" + currUser));
                        HttpResponseMessage thisMember = await client.GetAsync("api/Members?MemberStr=" + currUser);
                        var con = thisMember.Content;
                        var head = thisMember.Headers;
                        var rm = thisMember.RequestMessage;
                        int memID = Convert.ToInt32(thisMember.Content);//THIS IS THE LINE THAT GENERATES THE ERROR
                        //will need to call server's getidbyname method and pass result instead of currMember.memberID
                        //this.Frame.Navigate(typeof(HomeHub), currMember.memberID);
                        this.Frame.Navigate(typeof(HomeHub), memID);
                    }

                }

            }
            //MembersListBox.Items.Add(Members.MembersList.Count);
            foreach (var member in Members.MembersList)
            {
               // MembersListBox.Items.Add(member.ToString());
            }
        }
    }

这是我的服务项目中的控制器:

public class MembersController : ApiController
{
    private GatoradeShowerDB db = new GatoradeShowerDB();

    // GET: api/Members
    public IQueryable<Member> GetMembers()
    {
        return db.Members;
    }

    // GET: api/Members/5
    [ResponseType(typeof(Member))]
    public async Task<IHttpActionResult> GetMember(int id)
    {
        Member member = await db.Members.FindAsync(id);
        if (member == null)
        {
            return NotFound();
        }

        return Ok(member);
    }

    //GET: api/Members?MemberStr={memberStr}
    [ResponseType(typeof(Member))]
    public async Task<T> GetMemberIDByName<T>(String MemberStr) where T : struct
    {
        //var member = JsonConvert.DeserializeObject<Member>(MemberStr);
        //Member member = await db.Members.FindAsync(MemberStr);
        //var userId = ...;
        var member = await db.Members.Where(x => x.UserName == MemberStr).ToListAsync();
        if (member == null)
        {
            return (T)Convert.ChangeType(NotFound(), typeof(T));
        }
        return (T)Convert.ChangeType(member[0].MemberID, typeof(T));
        //return member[0].MemberID; //hopefully gets id of first member in async list and returns it
        //return Ok(member);
    }

//other methods
}

此外,这是我的客户端模型:

public class Members
{
    //[JsonProperty("MemberID")]
    //public int memberID { get; private set; }
    [JsonProperty("FirstName")]
    private string firstName { get; set; }
    [JsonProperty("LastName")]
    private string lastName { get; set; } //both names should be optional
    [JsonProperty("UserName")]
    public string userName { get; private set; } //note: I don't think we should track first and last names
    [JsonProperty("Password")]
    public string password { get; private set; } //will probably need to implement validation in setter so won't be able to auto-implement
    [JsonProperty("Email")]
    private string email { get; set; }//same with this. will need validation
    [JsonProperty("MemberCity")]
    private string memberCity { get; set; }
    [JsonProperty("MemberState")]
    private string memberState { get; set; }
    [JsonProperty("MemberZip")]
    private string memberZip { get; set; }
    [JsonProperty("MemberPhone")]
    private string memberPhone { get; set; }//should also be optional
    [JsonProperty("FaveTeamID")]
    private int faveTeamID { get; set; }

    public static List<Members> MembersList = new List<Members>();

    public Members(string first, string last, string user, string pass, string email, string city, string state, string zip, string phone, int team)
    {
        //memberID = id;
        firstName = first;
        lastName = last;
        userName = user;
        password = pass;
        this.email = email;
        memberCity = city;
        memberState = state;
        memberZip = zip;
        memberPhone = phone;
        faveTeamID = team;
    }

    public override string ToString()
    {
        return "Member: " + userName + " in " + memberCity;
    }

    public bool compareUserAndPassword(string currUser, string currPass)
    {
        if (currUser.Equals(userName) && currPass.Equals(password))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

最后,这是我的服务器端数据对象:

public partial class Member
{
    public int MemberID { get; set; }

    [Required]
    [StringLength(255)]
    public string FirstName { get; set; }

    [Required]
    [StringLength(255)]
    public string LastName { get; set; }

    [Required]
    [StringLength(50)]
    public string UserName { get; set; }

    [Required]
    [StringLength(32)]
    public string Password { get; set; }

    [Required]
    [StringLength(50)]
    public string Email { get; set; }

    [Required]
    [StringLength(50)]
    public string City { get; set; }

    [Required]
    [StringLength(30)]
    public string State { get; set; }

    [Required]
    [StringLength(255)]
    public string Zip { get; set; }

    [Required]
    [StringLength(255)]
    public string Phone { get; set; }

    public int FavTeamID { get; set; }
}

我知道这是很多代码,但我宁愿发布的内容太多而不是太少。我有一个想法是以某种方式将MemberID值添加到httpClient对象并将其作为参数传递给其他页面,但我不确定这是否可能。如果该值仅存储在服务器端数据对象中而不存储在客户端模型中,那么如何获取特定成员的MemberID值?如果有更简单的方法,我也会接受不同的方法。提前感谢您的帮助。

更新

我的问题似乎源自我的控制器中的GetMemberIDByName方法。当我调试它时,我收到以下错误消息:

无法在控制器'WorkingVersionGetItDone.Controllers.MembersController'上调用操作方法'System.Threading.Tasks.Task`1 [T] GetMemberIDByNameT',因为action方法是一种通用方法。

1 个答案:

答案 0 :(得分:1)

我很确定你的方法应该更像这样:

public async Task<IHttpActionResult> GetMemberIDByName(string MemberStr)
{
    var member = await db.Members.Where(x => x.UserName == MemberStr).ToListAsync();
    if (member == null)
    {
        return NotFound();
    }
    return Ok(member[0].MemberID);
}

然后,来电者将获得404(NotFound())或200 MemberID的有效负载,您可以进行适当的处​​理。

HttpResponseMessage memberResponse = await client.GetAsync("api/Members?MemberStr=" + currUser);

if(memberResponse.StatusCode == HttpStatusCode.OK)
{
    // got the memberId...
    var memberId = Convert.ToInt32( memberResponse.Content.ReadAsStringAsync().Result);
}
else if(memberResponse.StatusCode == HttpStatusCode.NotFound)
{
    // member not found...
}