- Home
- Forum
- ASP.NET Core - EJ 2
- Upload images in Razor Pages project without controller - Rich Text Editor
Upload images in Razor Pages project without controller - Rich Text Editor
Hi,
what's the recommended way to use a specific upload directory in Razor Pages projects, when using RTE?
I've seen an exmple https://ej2.syncfusion.com/aspnetcore/documentation/rich-text-editor/image/?no-cache=1. But this one uses controllers which is more related to the MVC pattern.
Can SaveURL also be used with Razor Pages when the handler method is in code behind?
E.g:
index.cshtml
<ejs-richtexteditor id="questionEditor" name="question">
<e-richtexteditor-insertimagesettings saveUrl="WHATTOUSEHERE" path="/.images/"></e-richtexteditor-insertimagesettings>
<e-richtexteditor-toolbarsettings items="@ViewData["ToolbarOptions"]"></e-richtexteditor-toolbarsettings>
<e-content-template>
</e-content-template>
</ejs-richtexteditor>
index.cshtml.cs
public async Task<IActionResult> OnPostUpload(List<IFormFile> UploadFiles)
{
...
}
Without providing any directy upload seems to work, at leas I get an URL within the img src tag. But can't find the image after uploading, so I thought it might be better to handle this manually
SIGN IN To post a reply.
11 Replies
PO
Prince Oliver
Syncfusion Team
May 7, 2019 10:46 AM UTC
Hello Felix,
Thank you for contacting us.
Query 1: “What's the recommended way to use a specific upload directory in Razor Pages projects, when using RTE? Can SaveURL also be used with Razor Pages when the handler method is in code behind?”
Yes. You can achieve upload using the saveUrl property and handler from code behind of Razor pages. But you need to add the below configurations to achieve it.
- Add AntiForgery token in startup file or web.config file.
[Startup.cs]
|
public void ConfigureServices(IServiceCollection services) // Add below code
{
services.AddMvc().AddJsonOptions(x =>
{
x.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
services.AddAntiforgery(o => o.HeaderName = "xsrf-token");
} |
- Setup AntiForgery token in uploading event of Rich Text Editor image uploader through object using toolbarClick event. We have added ValidateAntiForgeryToken attribute on the server-side method when Rich Text Editor image uploading event triggered.
[Index.cshtml]
|
@model IndexModel
@Html.AntiForgeryToken()
<ejs-richtexteditor id="rte" toolbarClick="toolbarClick">
<e-richtexteditor-insertimagesettings saveUrl="/Index?handler=Save" path="../">
</e-richtexteditor-insertimagesettings>
<e-content-template>
<p>
Users can format their content using standard toolbar commands.
</p>
</e-content-template>
</ejs-richtexteditor>
<script>
function toolbarClick(e) { // Triggered when you click the toolbar
if (e.item.id == "rte_toolbar_Image") { // Checked if image toolbar is clicked
var element = document.getElementById('rte_upload') // Image uploader element
element.ej2_instances[0].uploading = function upload(args) { // Added updating event on image uploader
args.currentRequest.setRequestHeader('XSRF-TOKEN', document.getElementsByName('__RequestVerificationToken')[0].value);
}
}
}
</script> |
[Index.cshtml.cs]
|
private IHostingEnvironment hostingEnv;
public IndexModel(IHostingEnvironment env)
{
this.hostingEnv = env;
}
[AcceptVerbs("Post")]
public IActionResult OnPostSave(IList<IFormFile> UploadFiles) // Triggered when uploading image
{
try
{
foreach (var file in UploadFiles)
{
if (UploadFiles != null)
{
var filename = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
filename = hostingEnv.WebRootPath + $@"\{filename}";
if (!System.IO.File.Exists(filename))
{
using (FileStream fs = System.IO.File.Create(filename))
{
file.CopyTo(fs);
fs.Flush();
}
}
else
{
Response.Clear();
Response.StatusCode = 204;
Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "File already exists.";
}
}
}
}
catch (Exception e)
{
Response.Clear();
Response.ContentType = "application/json; charset=utf-8";
Response.StatusCode = 204;
Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "No Content";
Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = e.Message;
}
return Content("");
} |
We have attached the example application for your reference, please find it in the following location:
http://www.syncfusion.com/downloads/support/directtrac/general/ze/RTE_razor_page_image_url1164633411
Query 2: “I've seen an example https://ej2.syncfusion.com/aspnetcore/documentation/rich-text-editor/image/?no-cache=1. But this one uses controllers which is more related to the MVC pattern.”
Currently, we have used MVC pattern for server-side actions in ASP.NET Core UG documentation.
Query 3: “Without providing any directly upload seems to work, at least I get an URL within the img src tag. But can't find the image after uploading, so I thought it might be better to handle this manually”
If you want to upload image without insertimagesettings property, you can upload the image directly and render it in editor. Suppose if you are going to configure insertimagesettings property, you need to specify path property. The editor considers the path property to render the image in editor. The saveUrl represents the URL to an action result method to save the image, and the path represents the destination folder in which the image must be saved.
Let us know if you need any further assistance on this.
Regards,
Prince
Hello Felix,
Thank you for contacting us.
Query 1: “What's the recommended way to use a specific upload directory in Razor Pages projects, when using RTE? Can SaveURL also be used with Razor Pages when the handler method is in code behind?”Yes. You can achieve upload using the saveUrl property and handler from code behind of Razor pages. But you need to add the below configurations to achieve it.
- Add AntiForgery token in startup file or web.config file.
[Startup.cs]
public void ConfigureServices(IServiceCollection services) // Add below code{services.AddMvc().AddJsonOptions(x =>{x.SerializerSettings.ContractResolver = new DefaultContractResolver();});services.AddAntiforgery(o => o.HeaderName = "xsrf-token");}
- Setup AntiForgery token in uploading event of Rich Text Editor image uploader through object using toolbarClick event. We have added ValidateAntiForgeryToken attribute on the server-side method when Rich Text Editor image uploading event triggered.
[Index.cshtml]
@model IndexModel@Html.AntiForgeryToken()<ejs-richtexteditor id="rte" toolbarClick="toolbarClick"><e-richtexteditor-insertimagesettings saveUrl="/Index?handler=Save" path="../"></e-richtexteditor-insertimagesettings><e-content-template><p>Users can format their content using standard toolbar commands.</p></e-content-template></ejs-richtexteditor><script>function toolbarClick(e) { // Triggered when you click the toolbarif (e.item.id == "rte_toolbar_Image") { // Checked if image toolbar is clickedvar element = document.getElementById('rte_upload') // Image uploader elementelement.ej2_instances[0].uploading = function upload(args) { // Added updating event on image uploaderargs.currentRequest.setRequestHeader('XSRF-TOKEN', document.getElementsByName('__RequestVerificationToken')[0].value);}}}</script>[Index.cshtml.cs]
private IHostingEnvironment hostingEnv;public IndexModel(IHostingEnvironment env){this.hostingEnv = env;}[AcceptVerbs("Post")]public IActionResult OnPostSave(IList<IFormFile> UploadFiles) // Triggered when uploading image{try{foreach (var file in UploadFiles){if (UploadFiles != null){var filename = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');filename = hostingEnv.WebRootPath + $@"\{filename}";if (!System.IO.File.Exists(filename)){using (FileStream fs = System.IO.File.Create(filename)){file.CopyTo(fs);fs.Flush();}}else{Response.Clear();Response.StatusCode = 204;Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "File already exists.";}}}}catch (Exception e){Response.Clear();Response.ContentType = "application/json; charset=utf-8";Response.StatusCode = 204;Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "No Content";Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = e.Message;}return Content("");}
We have attached the example application for your reference, please find it in the following location:http://www.syncfusion.com/downloads/support/directtrac/general/ze/RTE_razor_page_image_url1164633411Query 2: “I've seen an example https://ej2.syncfusion.com/aspnetcore/documentation/rich-text-editor/image/?no-cache=1. But this one uses controllers which is more related to the MVC pattern.”Currently, we have used MVC pattern for server-side actions in ASP.NET Core UG documentation.Query 3: “Without providing any directly upload seems to work, at least I get an URL within the img src tag. But can't find the image after uploading, so I thought it might be better to handle this manually”If you want to upload image without insertimagesettings property, you can upload the image directly and render it in editor. Suppose if you are going to configure insertimagesettings property, you need to specify path property. The editor considers the path property to render the image in editor. The saveUrl represents the URL to an action result method to save the image, and the path represents the destination folder in which the image must be saved.Let us know if you need any further assistance on this.
Regards,Prince
Hello Support,
Could you please provide an example using RAZOR pages (not MVC) using your Rich Text Editor? In the example that I read, it is using "ViewBag.value" to hold the content of the editor, however "ViewBag.value" is not possible to be used in RAZOR.
Can you please advise?
Thanks,
Flavio
PO
Prince Oliver
Syncfusion Team
May 22, 2019 09:19 AM UTC
Hello Flavio,
Thank you for the update.
You can use Model binding to pass value to the Value property in the RTE Control for the Razor pages. Please refer to the following code.
[Index.cshtml]
|
@model IndexModel
<ejs-richtexteditor id="rte" toolbarClick="toolbarClick" value="@Model.RteValue">
<e-richtexteditor-insertimagesettings saveUrl="/Index?handler=Save" path="../"></e-richtexteditor-insertimagesettings>
</ejs-richtexteditor> |
[Index.cshtml.cs]
|
public string RteValue { get; set; }
public void OnGet()
{
RteValue = "<p>This is <b>RTE</b> Content</p>";
} |
We have attached the modified sample for your reference, please find it in the following location:
Let us know if you need any further assistance on this.
Regards,
Prince
FL
Flavio
May 22, 2019 06:54 PM UTC
Hi Prince,
Thank you for your response.
Using your example, I could not save the RteValue OnPost(). Could you please let me know how can I get and save the RTE content using the OnPost() method in Razor pages?
Thanks,
Flavio
PO
Prince Oliver
Syncfusion Team
May 23, 2019 05:54 AM UTC
Hello Flavio,
Good day to you.
To get the value on the OnPost method, you need to bind the model to the ejs-for in RTE control. Then the model value can be accessed from the form data during the form post. Kindly refer to the following code.
[Index.cshtml]
|
<form method="post">
<ejs-richtexteditor ejs-for="RteValue" id="rte" toolbarClick="toolbarClick" >
<e-richtexteditor-insertimagesettings saveUrl="/Index?handler=Save" path="../"></e-richtexteditor-insertimagesettings>
</ejs-richtexteditor>
<br />
<input type="submit" />
</form> |
[Index.cshtml.cs]
|
public void OnPost(string RteValue)
{
var value = RteValue;
} |
Please find the modified sample for your reference: http://www.syncfusion.com/downloads/support/forum/144403/ze/WebApplication1581175088
Let us know if you need any further assistance on this.
Regards,
Prince
FE
Felix
May 27, 2019 05:59 PM UTC
Hi Prince,
it should also work with two instances on one site, right?
I've tried following but it's just working for the second RTE, the answer. My post method is pretty much the same as your's. But uploading an image in the first editor is not getting into the post method, seconds seems to work fine.
In Chrome I can see following error:
<div class="row">
<div class="col-lg-12">
<form method="post" asp-page-handler="post">
<div class="form-group">
<label asp-for="LearnContent.Question" class="control-label" ></label>
<ejs-richtexteditor id="questEditor" name="quest" toolbarClick="toolbarClickQuestion">
<e-richtexteditor-insertimagesettings saveUrl="Edit?handler=Save" path="../uploadedImages/"></e-richtexteditor-insertimagesettings>
<e-richtexteditor-toolbarsettings items="@ViewData["ToolbarOptions"]"></e-richtexteditor-toolbarsettings>
<e-content-template>
@Model.LearnContent.Question
</e-content-template>
</ejs-richtexteditor>
<script>
function toolbarClickQuestion(e) {
if (e.item.id == "questEditor_toolbar_Image") {
var element = document.getElementById('questEditor_upload')
element.ej2_instances[0].uploading = function upload(args) {
args.currentRequest.setRequestHeader('XSRF-TOKEN', document.getElementsByName('__RequestVerificationToken')[0].value);
}
}
}
</script>
</div>
<div class="form-group">
<label asp-for="LearnContent.Answer" class="control-label" ></label>
<ejs-richtexteditor id="answerEditor" name="answer" toolbarClick="toolbarClickAnswer">
<e-richtexteditor-insertimagesettings saveUrl="Edit?handler=Save" path="../uploadedImages/"></e-richtexteditor-insertimagesettings>
<e-richtexteditor-toolbarsettings items="@ViewData["ToolbarOptions"]"></e-richtexteditor-toolbarsettings>
<e-content-template>
@Model.LearnContent.Answer
</e-content-template>
</ejs-richtexteditor>
<script>
function toolbarClickAnswer(e) {
if (e.item.id == "answerEditor_toolbar_Image") {
var element = document.getElementById('answerEditor_upload')
element.ej2_instances[0].uploading = function upload(args) {
args.currentRequest.setRequestHeader('XSRF-TOKEN', document.getElementsByName('__RequestVerificationToken')[0].value);
}
}
}
</script>
</div>
<input type="hidden" asp-for="@Model.LearnContent.Id" name="id"/>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default"/>
</div>
</form>
</div>
</div>
CI
Christopher Issac Sunder K
Syncfusion Team
May 28, 2019 01:02 PM UTC
Hi Felix,
We have checked customer reported query on onPost method. We have created two ejs-for RTE component and triggered on the onPost method when submit the button. The RTE value is got properly on the server side. You can get the uploader object on ‘this.imageModule.uploadObj’ instead of getting elements using toolbarClick event. Please find the below code.
|
<form method="post">
<div class="form-group">
<ejs-richtexteditor ejs-for="RteValue" id="rte" toolbarClick="toolbarClick">
<e-richtexteditor-insertimagesettings saveUrl="/Index?handler=Save" path="../"></e-richtexteditor-insertimagesettings>
</ejs-richtexteditor>
</div>
<div class="form-group">
<ejs-richtexteditor ejs-for="RteValue1" id="rte1" toolbarClick="toolbarClick1">
<e-richtexteditor-insertimagesettings saveUrl="/Index?handler=Save" path="../"></e-richtexteditor-insertimagesettings>
</ejs-richtexteditor>
</div>
<br />
<input type="submit" />
</form>
<script>
function toolbarClick(e) {
if (e.item.id == "rte_toolbar_Image") {
this.imageModule.uploadObj.uploading = function upload(args) {
args.currentRequest.setRequestHeader('XSRF-TOKEN', document.getElementsByName('__RequestVerificationToken')[0].value);
}
}
}
function toolbarClick1(e) {
if (e.item.id == "rte1_toolbar_Image") {
this.imageModule.uploadObj.uploading = function upload(args) {
…..
}
}
}
</script> |
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/WebApplication1-1684137172
Please get back to us if you require any further assistance.
Thanks,
Christo
Christo
FE
Felix
May 29, 2019 04:28 PM UTC
perfect, works like a charm!
Just two questions regarding RTE in Asp.Net Core left :
When I'm changing the filename in the OnPostSave method before saving the file, it gets proper stored. But the "callback" to the rte element will have the original file name.
And how to use it within a table/loop?
I've changed it from foreach loop to a for loop to ensure very RTE will have an unique Id and name. But that didn't the trick.
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.LearnContentList[0].Picture)
th>
<th>
@Html.DisplayNameFor(model => model.LearnContentList[0].Question)
th>
<th>
@Html.DisplayNameFor(model => model.LearnContentList[0].Answer)
th>
<th>th>
tr>
thead>
<tbody>
@for (int i = 0; i < Model.LearnContentList.Count; i++){
<tr>
<td>
@Html.DisplayFor(modelItem => modelItem.LearnContentList[i].Question)
td>
<td>
<ejs-richtexteditor id="@i" name="@i + editor" value="@Model.LearnContentList[i].Answer" >
<e-richtexteditor-insertimagesettings path="../uploadedImages/">e-richtexteditor-insertimagesettings>
<e-content-template>e-content-template>
ejs-richtexteditor>
td>
<td>
<a asp-page="./Edit" asp-route-id="@Model.LearnContentList[i].Id">Edita> |
<a asp-page="./Details" asp-route-id="@Model.LearnContentList[i].Id">Detailsa> |
<a asp-page="./Delete" asp-route-id="@Model.LearnContentList[i].Id">Deletea>
td>
tr>
}
}
tbody>
table>
PO
Prince Oliver
Syncfusion Team
June 3, 2019 06:26 AM UTC
Hi Felix,
Good day to you
We checked the reported problem with getting the original file name in the callback function. Once you have renamed server end files, please update the renamed filename via response header. You can get the Response header on the Success event header of RTE. Using event arguments, you can now update the renamed file name and insert image to RTE. Please refer to the following example
[cshtml]
|
|
[CS]
|
|
We have attached the sample for your reference, please find it in the following location
Let us know if you need any further assistance on this.
Regards,
Prince
FE
Felix
June 5, 2019 05:42 PM UTC
Thx Prince,
very helpful.. as always. Have I missed this in the documentation? I'm still not able to find it there. Or is it so obvious that I'm the only one asking this? If so, sorry :).
Also, I found the issue regarding RTE within a loop. The id is does not allow to use a numeric only. Or it is used by another object already (can't find one but might be)
I'll changed it from
<ejs-richtexteditor id="@i" name="@i + editor" value="@Model.LearnContentList[i].Answer" >to
<ejs-richtexteditor id="test+@i" value="@Model.LearnContentList[i].Answer" >and had the same issue
but with:
<ejs-richtexteditor id="test_@i" value="@Model.LearnContentList[i].Answer" >it works perfectly.
PO
Prince Oliver
Syncfusion Team
June 6, 2019 10:08 AM UTC
Hi Felix,
Good day to you.
This is not yet documented, so we have considered to document this in our end and will be updated in our upcoming future releases. According to the current html behavior of the html element, the id value must begin with a letter ([A-Za-z]) and can be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"). Please find the below stack overflow link on your reference.
Hence, we suggest using id that contains at least one character. Let us know if you need any further assistance on this.
Regards,
Prince
SIGN IN To post a reply.
- 11 Replies
- 4 Participants
-
FE Felix
- May 5, 2019 09:13 AM UTC
- Jun 6, 2019 10:08 AM UTC