我正在将VueJS前端与vue-router和SignalR ASP.NET Core后端一起使用。
现在,我希望能够让我的客户连接到会议室,并仅将数据发送给该组的成员。我通过在后端使用两种方法来做到这一点,一种方法是创建一个房间,然后向它们发送一个12字符长的随机生成的字符串,该字符串存储在内存中,或者通过加入一个组,将这些字符串之一作为Join Room方法的参数来发送。现在,这可以正常工作,但我也希望能够通过链接附加到URL上的组ID字符串进行连接。那就是myurl.com/room/:groupId
,我打算通过路由到同一组件来实现,但是在后一种情况下,它具有一个带有URL参数:groupId
的属性集。这确实有效,并且在通常输入此groupId的对话框中,它已正确显示。
无论如何,导航到myurl.com/room/:groupId
时,我确实在DevTools中收到以下错误消息:
Error: Failed to complete negotiation with the server: SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
现在,我认为这与我的Startup.cs内部的后端配置有关,我已经从某个位置粘贴了此代码,以避开在不是“ /”的每个路径上获取404的问题:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseEndpoints(endpoints =>
{
Console.WriteLine(endpoints.ToString());
Console.WriteLine("^^^^^^^^^^^^^^^^^^^^^^");
endpoints.MapHub<DraftHub>("/drafthub");
});
//this function right here is what i mean, it sends index.html after assembling the path with vue-router i suppose?
app.Run( async (context) =>
{
context.Response.ContentType = "text/html";
await context.Response.SendFileAsync(Path.Combine(env.WebRootPath,"index.html"));
});
}
所以我想知道,该错误是否表示SignalR协商失败,因为资源库是text / html而不是text / json?如果是这种情况,那么为什么在我没有附加groupId的情况下导航到URL myurl.com/room
时协商不会失败?它使用相同的后备await context.Response.SendFileAsync(Path.Combine(env.WebRootPath,"index.html"));
吗?请注意,这两个路径都路由到我的前端中完全相同的Component,只有URL中带有groupId的路径将其作为prop传递,因此将其设置为默认值。
这里是组件的代码。
<template>
<base-view>
<join-dialog
v-model="visible"
:login-info.sync="loginInfo"
@click:create="createRoom"
@click:join="joinRoom"
/>
<chat-sidebar
:users="connectionInfo.groupConnections"
:my-name="loginInfo.userName"
:user="loginInfo.userName"
:group-id="connectionInfo.groupId"
/>
</base-view>
</template>
<script lang="ts">
import { defineComponent, ref, Ref } from "@vue/composition-api";
import JoinDialog from "@/components/JoinDialog.vue";
import ChatSidebar from "@/components/ChatSidebar.vue";
import ChessBoard from "@/components/Chess/ChessBoard.vue";
import {
sendCreateRoom,
onUpdateRoom,
ConnectionInfo,
sendJoinRoom,
start,
} from "@/service/signalr/draftHub";
import { createLoginInfo } from "../service/models";
export default defineComponent({
components: {
JoinDialog,
ChatSidebar,
ChessBoard,
},
props: {
groupId: { // THIS HERE IS SET WHEN URL HAS GROUP ID IN IT.
type: String,
default: () => "",
},
},
setup(props) {
const visible = ref(true);
const loginInfo = ref(createLoginInfo());
loginInfo.value.groupId = props.groupId; //ALREADY SET THE GROUP ID INCASE IT WAS IN THE URL
const connectionInfo: Ref<ConnectionInfo> = ref({});
const createRoom = () => {
sendCreateRoom(loginInfo.value.userName).then(
() => (visible.value = false)
);
};
const joinRoom = () => {
sendJoinRoom(loginInfo.value).then(() => (visible.value = false));
};
onUpdateRoom((connInfo: ConnectionInfo) => {
connectionInfo.value = connInfo;
console.log("running handler now to update users", connInfo);
});
start().then(() => console.log("connected to drafthub"));
return {
visible,
createRoom,
joinRoom,
loginInfo,
connectionInfo,
};
},
});
</script>
<style scoped></style>
这是我的vue-router设置:
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import Home from "../views/Home.vue";
import PrivateRoom from "../views/PrivateRoom.vue";
Vue.use(VueRouter);
const routes: Array<RouteConfig> = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
},
{
path: "/room",
name: "PrivateRoom",
component: PrivateRoom,
},
{
path: "/room/:groupId",
name: "PrivateRoomInstance",
component: PrivateRoom,
props: true,
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
export default router;
我希望我没有遗漏任何重要信息。如果我这样做的话,请给我打电话,非常感谢您的任何答复,我将不胜感激能指出正确的方向,因为我什至不知道它是否是路由器问题或信号发出者问题。
答案 0 :(得分:-1)
所以出现这种情况的原因是,我的SignalR集线器的路径是“ / drafthub”。 由于某种原因,转到前端路径“ / room”(未附加“ /”)会将协商请求发送到正确的路径,无论如何,一旦我有了“ / room /”,它将立即将其发送到路径“ / room / drafthub”,服务器将使用默认的404后备响应,即我的index.html进行响应,然后使用客户端路由。因此,从本质上讲,它提供了两次服务,一次是在我键入URL时,另一次是我尝试升级到signalR连接。
FIX :
我仍在尝试找出将其精确映射到“ / room / drafthub”的原因,但现在我也只是在我的后端的ConfigureServices
方法中将Drafthub映射到了该端点:
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<DraftHub>("/drafthub");
endpoints.MapHub<DraftHub>("/room/drafthub");
});