#182 options api is now complete
This commit is contained in:
parent
7015087393
commit
31a4bbd910
22
RMuseum/Controllers/RGenericOptionsController.cs
Normal file
22
RMuseum/Controllers/RGenericOptionsController.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RSecurityBackend.Controllers;
|
||||
using RSecurityBackend.Services;
|
||||
|
||||
namespace RMuseum.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// options
|
||||
/// </summary>
|
||||
[Produces("application/json")]
|
||||
[Route("api/options")]
|
||||
public class RGenericOptionsController : RGenericOptionsControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="optionsService"></param>
|
||||
public RGenericOptionsController(IRGenericOptionsService optionsService) : base(optionsService)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ namespace RMuseum.DbContext
|
||||
{
|
||||
public RMuseumDbContext(DbContextOptions<RMuseumDbContext> options) : base(options)
|
||||
{
|
||||
//Database.Migrate();
|
||||
Database.Migrate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
2684
RMuseum/Migrations/20210721050043_Options.Designer.cs
generated
Normal file
2684
RMuseum/Migrations/20210721050043_Options.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
45
RMuseum/Migrations/20210721050043_Options.cs
Normal file
45
RMuseum/Migrations/20210721050043_Options.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace RMuseum.Migrations
|
||||
{
|
||||
public partial class Options : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Options",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
Name = table.Column<string>(type: "nvarchar(450)", nullable: true),
|
||||
Value = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
RAppUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Options", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Options_AspNetUsers_RAppUserId",
|
||||
column: x => x.RAppUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Options_RAppUserId_Name",
|
||||
table: "Options",
|
||||
columns: new[] { "RAppUserId", "Name" },
|
||||
unique: true,
|
||||
filter: "[RAppUserId] IS NOT NULL AND [Name] IS NOT NULL");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Options");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1848,6 +1848,31 @@ namespace RMuseum.Migrations
|
||||
b.ToTable("VerifyQueueItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RSecurityBackend.Models.Generic.Db.RGenericOption", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<Guid?>("RAppUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RAppUserId", "Name")
|
||||
.IsUnique()
|
||||
.HasFilter("[RAppUserId] IS NOT NULL AND [Name] IS NOT NULL");
|
||||
|
||||
b.ToTable("Options");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RSecurityBackend.Models.Generic.Db.RLongRunningJobStatus", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@ -2576,6 +2601,15 @@ namespace RMuseum.Migrations
|
||||
b.Navigation("RAppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RSecurityBackend.Models.Generic.Db.RGenericOption", b =>
|
||||
{
|
||||
b.HasOne("RSecurityBackend.Models.Auth.Db.RAppUser", "RAppUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("RAppUserId");
|
||||
|
||||
b.Navigation("RAppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RSecurityBackend.Models.Notification.RUserNotification", b =>
|
||||
{
|
||||
b.HasOne("RSecurityBackend.Models.Auth.Db.RAppUser", "User")
|
||||
|
||||
@ -1468,6 +1468,17 @@
|
||||
IAppUserService instance
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Controllers.RGenericOptionsController">
|
||||
<summary>
|
||||
options
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.RGenericOptionsController.#ctor(RSecurityBackend.Services.IRGenericOptionsService)">
|
||||
<summary>
|
||||
constructor
|
||||
</summary>
|
||||
<param name="optionsService"></param>
|
||||
</member>
|
||||
<member name="T:RMuseum.Controllers.RImageController">
|
||||
<summary>
|
||||
Generic Image Provider
|
||||
|
||||
@ -276,6 +276,9 @@ namespace RMuseum
|
||||
//long running job service
|
||||
services.AddTransient<ILongRunningJobProgressService, LongRunningJobProgressServiceEF>();
|
||||
|
||||
//generic options service
|
||||
services.AddTransient<IRGenericOptionsService, RGenericOptionsServiceEF>();
|
||||
|
||||
//site banner service
|
||||
services.AddTransient<ISiteBannersService, SiteBannersService>();
|
||||
|
||||
|
||||
108
RSecurityBackend/Controllers/RGenericOptionsControllerBase.cs
Normal file
108
RSecurityBackend/Controllers/RGenericOptionsControllerBase.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RSecurityBackend.Models.Auth.Memory;
|
||||
using RSecurityBackend.Services;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace RSecurityBackend.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// options controller
|
||||
/// </summary>
|
||||
[Produces("application/json")]
|
||||
[Route("api/options")]
|
||||
public abstract class RGenericOptionsControllerBase : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// get user level option
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{name}")]
|
||||
[Authorize]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
public async Task<IActionResult> GetValue(string name)
|
||||
{
|
||||
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
|
||||
var res = await _optionsService.GetValueAsync(name, loggedOnUserId);
|
||||
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||
return BadRequest(res.ExceptionString);
|
||||
return Ok(res.Result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// get user level option
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut("{name}")]
|
||||
[Authorize]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
public async Task<IActionResult> SetValue(string name, [FromBody] string value)
|
||||
{
|
||||
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
|
||||
var res = await _optionsService.SetAsync(name, value, loggedOnUserId);
|
||||
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||
return BadRequest(res.ExceptionString);
|
||||
return Ok(res.Result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// get global option value
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
[HttpGet("global/{name}")]
|
||||
[Authorize(Policy = SecurableItem.GlobalOptionsEntityShortName + ":" + SecurableItem.ViewOperationShortName)]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
public async Task<IActionResult> GetGlobalOptionValue(string name)
|
||||
{
|
||||
var res = await _optionsService.GetValueAsync(name, null);
|
||||
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||
return BadRequest(res.ExceptionString);
|
||||
return Ok(res.Result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// set global option value
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut("global/{name}")]
|
||||
[Authorize(Policy = SecurableItem.GlobalOptionsEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
public async Task<IActionResult> SetGlobalOptionValue(string name, [FromBody] string value)
|
||||
{
|
||||
var res = await _optionsService.SetAsync(name, value, null);
|
||||
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||
return BadRequest(res.ExceptionString);
|
||||
return Ok(res.Result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="optionsService">
|
||||
/// </param>
|
||||
public RGenericOptionsControllerBase(IRGenericOptionsService optionsService)
|
||||
{
|
||||
_optionsService = optionsService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options Service
|
||||
/// </summary>
|
||||
protected readonly IRGenericOptionsService _optionsService;
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,7 @@ namespace RSecurityBackend.Controllers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Artifact Service
|
||||
/// Jobs Service
|
||||
/// </summary>
|
||||
protected readonly ILongRunningJobProgressService _jobService;
|
||||
}
|
||||
|
||||
@ -64,8 +64,9 @@ namespace RSecurityBackend.DbContext
|
||||
.IsUnique();
|
||||
|
||||
builder.Entity<RGenericOption>()
|
||||
.HasIndex(o => o.Name)
|
||||
.HasIndex(o => new { o.RAppUserId, o.Name })
|
||||
.IsUnique();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -19,6 +19,11 @@
|
||||
/// </summary>
|
||||
public const string AuditLogEntityShortName = "audit";
|
||||
|
||||
/// <summary>
|
||||
/// global options
|
||||
/// </summary>
|
||||
public const string GlobalOptionsEntityShortName = "option";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// view
|
||||
@ -105,6 +110,16 @@
|
||||
{
|
||||
new SecurableItemOperation(ViewOperationShortName, "مشاهده", false),
|
||||
}
|
||||
},
|
||||
new SecurableItem()
|
||||
{
|
||||
ShortName = GlobalOptionsEntityShortName,
|
||||
Description = "تنظیمات عمومی",
|
||||
Operations = new SecurableItemOperation[]
|
||||
{
|
||||
new SecurableItemOperation(ViewOperationShortName, "مشاهده", false),
|
||||
new SecurableItemOperation(ModifyOperationShortName, "اصلاح", false),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
namespace RSecurityBackend.Models.Generic.Db
|
||||
using RSecurityBackend.Models.Auth.Db;
|
||||
using System;
|
||||
|
||||
namespace RSecurityBackend.Models.Generic.Db
|
||||
{
|
||||
/// <summary>
|
||||
/// generic option
|
||||
@ -19,5 +22,15 @@
|
||||
///value
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// user id
|
||||
/// </summary>
|
||||
public Guid? RAppUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// user
|
||||
/// </summary>
|
||||
public virtual RAppUser RAppUser { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -394,6 +394,53 @@
|
||||
</summary>
|
||||
<param name="notificationService"></param>
|
||||
</member>
|
||||
<member name="T:RSecurityBackend.Controllers.RGenericOptionsControllerBase">
|
||||
<summary>
|
||||
options controller
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Controllers.RGenericOptionsControllerBase.GetValue(System.String)">
|
||||
<summary>
|
||||
get user level option
|
||||
</summary>
|
||||
<param name="name"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Controllers.RGenericOptionsControllerBase.SetValue(System.String,System.String)">
|
||||
<summary>
|
||||
get user level option
|
||||
</summary>
|
||||
<param name="name"></param>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Controllers.RGenericOptionsControllerBase.GetGlobalOptionValue(System.String)">
|
||||
<summary>
|
||||
get global option value
|
||||
</summary>
|
||||
<param name="name"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Controllers.RGenericOptionsControllerBase.SetGlobalOptionValue(System.String,System.String)">
|
||||
<summary>
|
||||
set global option value
|
||||
</summary>
|
||||
<param name="name"></param>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Controllers.RGenericOptionsControllerBase.#ctor(RSecurityBackend.Services.IRGenericOptionsService)">
|
||||
<summary>
|
||||
constructor
|
||||
</summary>
|
||||
<param name="optionsService">
|
||||
</param>
|
||||
</member>
|
||||
<member name="F:RSecurityBackend.Controllers.RGenericOptionsControllerBase._optionsService">
|
||||
<summary>
|
||||
Options Service
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RSecurityBackend.Controllers.RImageControllerBase">
|
||||
<summary>
|
||||
Generic Image Provider
|
||||
@ -457,7 +504,7 @@
|
||||
</member>
|
||||
<member name="F:RSecurityBackend.Controllers.RLongRunningJobsControllerBase._jobService">
|
||||
<summary>
|
||||
Artifact Service
|
||||
Jobs Service
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RSecurityBackend.Controllers.RoleControllerBase">
|
||||
@ -1003,6 +1050,11 @@
|
||||
audit
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:RSecurityBackend.Models.Auth.Memory.SecurableItem.GlobalOptionsEntityShortName">
|
||||
<summary>
|
||||
global options
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:RSecurityBackend.Models.Auth.Memory.SecurableItem.ViewOperationShortName">
|
||||
<summary>
|
||||
view
|
||||
@ -1769,6 +1821,16 @@
|
||||
value
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RSecurityBackend.Models.Generic.Db.RGenericOption.RAppUserId">
|
||||
<summary>
|
||||
user id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RSecurityBackend.Models.Generic.Db.RGenericOption.RAppUser">
|
||||
<summary>
|
||||
user
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RSecurityBackend.Models.Generic.Db.RLongRunningJobStatus">
|
||||
<summary>
|
||||
Long Running Job Status
|
||||
@ -3300,19 +3362,21 @@
|
||||
generic options service
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Services.Implementation.RGenericOptionsServiceEF.SetAsync(System.String,System.String)">
|
||||
<member name="M:RSecurityBackend.Services.Implementation.RGenericOptionsServiceEF.SetAsync(System.String,System.String,System.Nullable{System.Guid})">
|
||||
<summary>
|
||||
modify an option or add a new one if an option with the requested name does not exist
|
||||
</summary>
|
||||
<param name="optionName"></param>
|
||||
<param name="optionValue"></param>
|
||||
<param name="userId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Services.Implementation.RGenericOptionsServiceEF.GetValueAsync(System.String)">
|
||||
<member name="M:RSecurityBackend.Services.Implementation.RGenericOptionsServiceEF.GetValueAsync(System.String,System.Nullable{System.Guid})">
|
||||
<summary>
|
||||
get option value
|
||||
</summary>
|
||||
<param name="optionName"></param>
|
||||
<param name="userId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="F:RSecurityBackend.Services.Implementation.RGenericOptionsServiceEF._context">
|
||||
@ -3533,19 +3597,21 @@
|
||||
generic options service
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Services.IRGenericOptionsService.SetAsync(System.String,System.String)">
|
||||
<member name="M:RSecurityBackend.Services.IRGenericOptionsService.SetAsync(System.String,System.String,System.Nullable{System.Guid})">
|
||||
<summary>
|
||||
modify an option or add a new one if an option with the requested name does not exist
|
||||
</summary>
|
||||
<param name="optionName"></param>
|
||||
<param name="optionValue"></param>
|
||||
<param name="userId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Services.IRGenericOptionsService.GetValueAsync(System.String)">
|
||||
<member name="M:RSecurityBackend.Services.IRGenericOptionsService.GetValueAsync(System.String,System.Nullable{System.Guid})">
|
||||
<summary>
|
||||
get option value
|
||||
</summary>
|
||||
<param name="optionName"></param>
|
||||
<param name="userId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:RSecurityBackend.Services.IRNotificationService">
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using RSecurityBackend.Models.Generic;
|
||||
using RSecurityBackend.Models.Generic.Db;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RSecurityBackend.Services
|
||||
@ -14,14 +15,16 @@ namespace RSecurityBackend.Services
|
||||
/// </summary>
|
||||
/// <param name="optionName"></param>
|
||||
/// <param name="optionValue"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task<RServiceResult<RGenericOption>> SetAsync(string optionName, string optionValue);
|
||||
Task<RServiceResult<RGenericOption>> SetAsync(string optionName, string optionValue, Guid? userId);
|
||||
|
||||
/// <summary>
|
||||
/// get option value
|
||||
/// </summary>
|
||||
/// <param name="optionName"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task<RServiceResult<string>> GetValueAsync(string optionName);
|
||||
Task<RServiceResult<string>> GetValueAsync(string optionName, Guid? userId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,10 +19,11 @@ namespace RSecurityBackend.Services.Implementation
|
||||
/// </summary>
|
||||
/// <param name="optionName"></param>
|
||||
/// <param name="optionValue"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<RServiceResult<RGenericOption>> SetAsync(string optionName, string optionValue)
|
||||
public async Task<RServiceResult<RGenericOption>> SetAsync(string optionName, string optionValue, Guid? userId)
|
||||
{
|
||||
var existing = await _context.Options.Where(o => o.Name == optionName).SingleOrDefaultAsync();
|
||||
var existing = await _context.Options.Where(o => o.Name == optionName && o.RAppUserId == userId).SingleOrDefaultAsync();
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Value = optionValue;
|
||||
@ -35,7 +36,8 @@ namespace RSecurityBackend.Services.Implementation
|
||||
var option = new RGenericOption()
|
||||
{
|
||||
Name = optionName,
|
||||
Value = optionValue
|
||||
Value = optionValue,
|
||||
RAppUserId = userId
|
||||
};
|
||||
|
||||
_context.Options.Add(option);
|
||||
@ -48,12 +50,13 @@ namespace RSecurityBackend.Services.Implementation
|
||||
/// get option value
|
||||
/// </summary>
|
||||
/// <param name="optionName"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<RServiceResult<string>> GetValueAsync(string optionName)
|
||||
public async Task<RServiceResult<string>> GetValueAsync(string optionName, Guid? userId)
|
||||
{
|
||||
var option = await _context.Options.AsNoTracking().Where(o => o.Name == optionName).SingleOrDefaultAsync();
|
||||
var option = await _context.Options.AsNoTracking().Where(o => o.Name == optionName && o.RAppUserId == userId).SingleOrDefaultAsync();
|
||||
if (option == null)
|
||||
return new RServiceResult<string>(null, $"option '{optionName}' not found!");
|
||||
return new RServiceResult<string>(""); //empty value
|
||||
return new RServiceResult<string>(option.Value);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user