You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebForms页面用Refit调用REST API报错 求示例及解决方案

问题分析与解决方法

你遇到的System.Net.ProtocolViolationException错误,核心原因是GET请求携带了请求体(Body)——HTTP规范中,GET请求通常不包含请求体,.NET的底层HttpWebRequest默认会阻止这种不符合规范的请求,所以抛出了这个错误。

下面分两种场景给出解决方法,优先推荐第一种(符合REST设计规范):


方案1:改用POST请求(推荐)

登录操作属于提交数据的行为,用POST请求更符合REST规范,也能从根源避免GET带Body的问题。

修改后的ILogin接口

namespace Dashboard.Sdk {
    using Dashboard.Common.Modelos;
    using Refit;
    using System.Threading.Tasks;

    public interface ILogin {
        // 把[Get]改为[Post],同时修正路径(原路径中的#应该是输入错误)
        [Post("/comGpsGate/api/v.1/test/Tokens")]
        Task<ApiResponse<AuthSuccessResponse>> GetLogin([Body] Login login);
    }
}

WebForms页面代码(无需大幅修改)

注意:要确保你的ASPX页面指令中添加了Async="true",否则异步操作可能出现线程问题:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" Async="true" %>

后台代码保持原有逻辑即可,同时补充更严谨的请求成功判断:

protected async void btnAcceder_Click(object sender, EventArgs e) {
    try {
        var api = RestService.For<ILogin>("https://WebApi.Test");
        var login = await api.GetLogin(new Login { 
            UserName = TxtEmail.Text, 
            Password = TxtPassword.Text 
        });

        if (login == null || !login.IsSuccessStatusCode) {
            Response.Redirect("Error.aspx?Err=102");
            return;
        }

        Session["Usuario"] = login.Content.Token;
        Response.Redirect("Dashboard.aspx");
    } catch (Exception ex) {
        // 可添加异常日志记录逻辑
        Response.Redirect("Error.aspx?Err=103");
    }
}

方案2:如果必须使用GET请求(不推荐)

如果目标API强制要求用GET传递参数,那么不能用[Body],需要把参数转为URL查询字符串传递:

修改后的ILogin接口(单个参数传递)

namespace Dashboard.Sdk {
    using Dashboard.Common.Modelos;
    using Refit;
    using System.Threading.Tasks;

    public interface ILogin {
        [Get("/comGpsGate/api/v.1/test/Tokens")]
        Task<ApiResponse<AuthSuccessResponse>> GetLogin(
            [Query] string userName, 
            [Query] string password
        );
    }
}

后台调用代码

protected async void btnAcceder_Click(object sender, EventArgs e) {
    try {
        var api = RestService.For<ILogin>("https://WebApi.Test");
        var login = await api.GetLogin(TxtEmail.Text, TxtPassword.Text);

        if (login == null || !login.IsSuccessStatusCode) {
            Response.Redirect("Error.aspx?Err=102");
            return;
        }

        Session["Usuario"] = login.Content.Token;
        Response.Redirect("Dashboard.aspx");
    } catch (Exception ex) {
        Response.Redirect("Error.aspx?Err=103");
    }
}

如果你的Login类有多个属性,也可以用[QueryUri]自动序列化对象为查询字符串:

public interface ILogin {
    [Get("/comGpsGate/api/v.1/test/Tokens{?*}")]
    Task<ApiResponse<AuthSuccessResponse>> GetLogin([QueryUri] Login login);
}

额外注意事项

  • WebForms中使用async void处理按钮事件是允许的,但建议添加try-catch块捕获异步异常,避免未处理异常导致页面崩溃;
  • 确保Refit版本与.NET Framework版本兼容(推荐使用Refit v6.x及以上版本,支持.NET Framework 4.6.1+);
  • 原接口路径中的#是无效的URL字符,必须去掉,否则会导致请求路径解析错误。

内容的提问来源于stack exchange,提问作者José Donoso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:22:38