如何通过API在SenseNet数据库保存自定义实体并创建对应模型?
我来帮你梳理下在SenseNet中创建自定义实体模型并保存数据的具体步骤,优先覆盖你想要的ASP.NET方案,再补充前端API的选项:
一、创建自定义实体模型(优先ASP.NET后端实现)
SenseNet的自定义内容类型(对应你的模型)可以通过代码类或者XML定义文件(CTD)来创建,推荐用代码类的方式在ASP.NET项目中实现,更贴合.NET生态:
1. 定义内容类型类
在你的ASP.NET项目中创建一个继承自GenericContent的类,标记内容类型名称并定义字段:
using SenseNet.ContentRepository; using SenseNet.ContentRepository.Schema; [ContentTypeName("PersonEntity")] public class PersonEntity : GenericContent { // 对应你的TypeScript实体中的name字段(复用SenseNet内置的DisplayName作为显示名称) [RepositoryProperty("DisplayName", RepositoryDataType.Text)] public string DisplayName { get => base.GetProperty<string>("DisplayName"); set => base.SetProperty("DisplayName", value); } // 对应你的TypeScript实体中的email字段 [RepositoryProperty("Email", RepositoryDataType.Text)] public string Email { get => base.GetProperty<string>("Email"); set => base.SetProperty("Email", value); } // 后续添加图片字段的示例(Binary类型) //[RepositoryProperty("ProfileImage", RepositoryDataType.Binary)] //public BinaryData ProfileImage //{ // get => base.GetProperty<BinaryData>("ProfileImage"); // set => base.SetProperty("ProfileImage", value); //} // 必要的构造函数 public PersonEntity(Node parent) : base(parent) { } public PersonEntity(NodeToken nt) : base(nt) { } }
注意:SenseNet中每个节点都有一个唯一的
Name属性(用于URL路径),这里我们复用内置的DisplayName存储你的name字段,节点的Name可以用邮箱或生成的唯一值设置(后面保存时会提到)。
2. 注册内容类型
在项目启动时(比如Startup.cs或Program.cs)注册这个内容类型,让SenseNet识别它:
// 在应用初始化阶段添加 ContentManager.RegisterContentType(typeof(PersonEntity));
备选:用CTD文件定义(XML方式)
如果你更习惯用XML配置,可以在SenseNet的ContentTypes文件夹下创建PersonEntity.ctd文件,内容如下:
<ContentType name="PersonEntity" parentType="GenericContent" handler="YourNamespace.PersonEntity, YourAssemblyName"> <DisplayName>Person Entity</DisplayName> <Description>Custom person entity with name and email fields</Description> <Fields> <Field name="DisplayName" type="Text"> <DisplayName>Name</DisplayName> <Configuration> <Required>true</Required> </Configuration> </Field> <Field name="Email" type="Text"> <DisplayName>Email</DisplayName> <Configuration> <Required>true</Required> <RegexPattern>^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$</RegexPattern> </Configuration> </Field> <!-- 后续图片字段配置 --> <!--<Field name="ProfileImage" type="Binary"> <DisplayName>Profile Image</DisplayName> <Configuration> <AllowedExtensions>.jpg,.jpeg,.png</AllowedExtensions> </Configuration> </Field>--> </Fields> </ContentType>
二、前端API创建模型(不推荐,仅管理员可用)
如果必须通过前端API创建内容类型,需要使用SenseNet的OData Admin API,且调用者必须有管理员权限。发送POST请求到/odata.svc/ContentTypes,请求体如下:
{ "__ContentType": "ContentType", "Name": "PersonEntity", "ParentPath": "/Root/ContentTypes/GenericContent", "DisplayName": "Person Entity", "Fields": [ { "Name": "DisplayName", "Type": "Text", "Configuration": { "Required": true } }, { "Name": "Email", "Type": "Text", "Configuration": { "Required": true, "RegexPattern": "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$" } } ] }
注意:这种方式风险较高,因为内容类型定义涉及数据结构,建议还是通过后端代码维护。
三、保存实体的POST请求配置
创建好模型后,你需要通过SenseNet的OData API来创建PersonEntity实例,具体配置如下:
1. API端点URL
POST请求的URL格式为:/odata.svc/[父节点路径]/CreateDocument
- 比如你要把人员实体保存在
/Root/People这个父文件夹下(需要先在SenseNet中创建这个文件夹),URL就是:/odata.svc/Root/People/CreateDocument
2. 请求头设置
Content-Type: application/json(仅当发送JSON数据时)Authorization: Bearer {你的授权Token}(需要先通过SenseNet的认证接口获取Token)
3. Angular代码示例(保存基础字段)
结合你的TypeScript实体,创建一个服务来发送请求:
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { PersonEntity } from './person-entity'; @Injectable({ providedIn: 'root' }) export class PersonService { private baseApiUrl = '/odata.svc/Root/People/CreateDocument'; private authToken = 'your-auth-token-here'; // 替换为实际获取的Token constructor(private http: HttpClient) { } createPerson(person: PersonEntity) { // 构造SenseNet要求的请求体,注意节点Name必须唯一 const requestBody = { "__ContentType": "PersonEntity", "Name": person.email.replace(/[@.]/g, '-'), // 用邮箱生成唯一节点名称 "DisplayName": person.name, // 映射到你的name字段 "Email": person.email }; const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.authToken}` }) }; return this.http.post(this.baseApiUrl, requestBody, httpOptions); } }
4. 后续添加图片字段的上传示例
当需要上传图片时,要改用multipart/form-data格式,用FormData来构造请求体:
createPersonWithImage(person: PersonEntity, imageFile: File) { const formData = new FormData(); formData.append('__ContentType', 'PersonEntity'); formData.append('Name', person.email.replace(/[@.]/g, '-')); formData.append('DisplayName', person.name); formData.append('Email', person.email); formData.append('ProfileImage', imageFile, imageFile.name); const httpOptions = { headers: new HttpHeaders({ 'Authorization': `Bearer ${this.authToken}` // 不要手动设置Content-Type,浏览器会自动添加正确的边界 }) }; return this.http.post(this.baseApiUrl, formData, httpOptions); }
内容的提问来源于stack exchange,提问作者Janneman96

