Is there a way for Code Block feature to keep line breaks in CKEditor5 with ASP.Net Core? - asp.net-core

I am making a bulletin board system using CKEditor. Most of the features work just fine, but when editing an existing post, the all line breaks in the text are removed from the code block.
Image of create a post
Image of edit a post
Image of part of the response source
I googled as much as possible to solve this problem, but the methods I found were to no avail, so I removed it from the code again.
It seems that line breaks are removed while processing the source internally in CKEditor5, is there any way?
Replace all line breaks with <br /> tags.
Add /\r|\n/g to protectedSource
The following is the view file for that feature.
#model BBSArticleWriteView
#{
// Action name of the current view
var thisActionString = #ViewContext.RouteData.Values["action"].ToString();
if (Model.ArticleId == null)
ViewData["Title"] = "Writing";
else
ViewData["Title"] = "Editing";
}
<p class="page-header">#ViewData["Title"]</p>
<form asp-action="#thisActionString" id="editor-form">
<input asp-for="ArticleId" value="#Model.ArticleId" hidden />
<div>
<input asp-for="Title" required placeholder="Please enter a title." class="form-control w-100 mb-2" />
</div>
<div>
<textarea name="Contents" id="editor">
#Html.Raw(Model.Contents)
</textarea>
</div>
<div>
<input class="btn btn-sm btn-primary" type="submit" value="Save" onsubmit="Editor.submit()" />
<button class="btn btn-sm btn-primary" type="button" href="##" onclick="history.back()">Back</button>
</div>
</form>
<style>
.ck-editor__editable_inline {
min-height: 400px;
}
</style>
#section Scripts {
<script src="~/lib/ckeditor5/ckeditor.js" asp-append-version="true"></script>
<script>
class Editor{
static submit() {
return true;
}
}
ClassicEditor
.create(document.querySelector('#editor'),
{
simpleUpload:{
uploadUrl: "#Url.Action(nameof(CreatorFront.Controllers.FileController.Upload), "File")",
withCredentials: true
},
protectedSource:[
/\r|\n/g
]
})
.catch(error => {
console.error(error);
});
</script>
}
And here is the controller action that puts data into the view model.
[HttpGet]
public async Task<IActionResult> BBSEdit(int id)
{
var user = await _userManager.GetUserAsync(HttpContext.User);
if(user == null)
{
return RedirectToAction("Index", "Home");
}
var article = _cContext.BBSArticle.First(a => a.ArticleId == id);
if(article == null)
{
return RedirectToAction(nameof(BBSList));
}
if(user.Id != article.UserId)
{
return RedirectToAction(nameof(BBSList));
}
var model = new BBSArticleWriteView();
CopyProperties(model, article);
return View(nameof(BBSWrite), model);
}
The following is a function that puts content data in DB.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> BBSWrite(BBSArticleWriteView article)
{
if(ModelState.IsValid)
{
var user = await _userManager.GetUserAsync(HttpContext.User);
if(user == null)
{
RedirectToAction("Index", "Home");
}
// XSS attacks prevent
article.Contents = _htmlSanitizer.Sanitize(article.Contents);
var currentDateTime = DateTime.Now;
CreatorLib.Models.BBS.BBSArticle data = new CreatorLib.Models.BBS.BBSArticle()
{
ArticleId = _cContext.BBSArticle.Max(a => a.ArticleId) + 1,
MainCategory = article.MainCategory,
SubCategory = article.SubCategory,
UserId = user.Id,
Title = article.Title,
Contents = article.Contents,
Status = CreatorLib.Models.BBS.ArticleStatus.A,
IpAddress = HttpContext.Connection.RemoteIpAddress.ToString(),
RegisteredTime = currentDateTime,
LastUpdatedTime = currentDateTime,
HasMedia = article.HasMedia
};
_cContext.BBSArticle.Add(data);
await _cContext.SaveChangesAsync();
return RedirectToAction(nameof(BBSList));
}
return View(article);
}
Here, it is confirmed that HtmlSanitizer has absolutely no impact on this issue.
In DB, line breaks are fully preserved.

Related

Adding İtems in Shopping cart

I've been working on my shopping cart program, but I keep having problems with adding an item to the shopping cart
here is my code;
HomeController class
[HttpPost]
public ActionResult AddToBasket(int id)
{
var basketJson = HttpContext.Session.GetString(SESSION_KEY);
List<SepetProduct> sepet;
if (basketJson == null)
{
sepet = new List<SepetProduct>();
}
else
{
sepet = JsonSerializer.Deserialize<List<SepetProduct>>(basketJson);
}
if (sepet.Any(x=> x.id == id))
{
sepet.Single(x => x.id == id).Toplam++;
}
else
{
sepet.Add(new SepetProduct { id = id, Toplam = 1 });
}
basketJson = JsonSerializer.Serialize(sepet);
HttpContext.Session.SetString(SESSION_KEY, basketJson);
return Json(new { status = true, Msg = "Ürün Sepete Eklendi", Data = sepet });
}
'''
and here is my Button action code
<form action="#Url.Action("addToBasket","Home")" method="post" enctype="multipart/form-data">
<input type="hidden" name="Id" value="#urun.UrunId" />
<button type="submit" class="btn btn-dark">
<span class="fa fa-shopping-cart"></span>Sepete ekle
</button>
</form>
The problem is that, when ı press to "sepete ekle" button, item was added to cart, but it directs us to a new page called "https://localhost:44302/Home/addToBasket"
and show us those data
'''
status true
msg "Ürün Sepete Eklendi"
data
0
id 2
toplam 1
'''
I would like to when ı press to 'sepete ekle ' button, the page remains the same, but the product is added to the basket. it just shows us a message saying added.
How can ı do that. thank you for interesting and helping
You can try to use ajax to replace form post.Here is a working demo:
TestBasket.cshtml(I use value="1" to test.And add id="Id" to hidden input.Also,I need to change the type of button,so that when click it,it will not submit form,it will go to submitData() function.):
<form action="#Url.Action("addToBasket","Home")" method="post" enctype="multipart/form-data">
<input type="hidden" id="Id" name="Id" value="1" />
<button type="button" onclick="submitData()" class="btn btn-dark">
<span class="fa fa-shopping-cart"></span>Sepete ekle
</button>
</form>
<script>
function submitData() {
$.ajax({
type: "POST",
url: '#Url.Action("addToBasket","Home")',
data: { "id": $("#Id").val() }
}).done(function (data) {
console.log(data.msg);
});
}
</script>
HomeController:
public IActionResult TestBasket()
{
return View();
}
[HttpPost]
public ActionResult AddToBasket(int id)
{
return Json(new { status = true, Msg = "Ürün Sepete Eklendi", Data = new List<SepetProduct>() });
}
result:

Any Idea how to handle file input fields when updating a form

I am using asp.net core 3.1 with Razor forms.
I have a form that contains an input of type file and it is multiple files input.
In the create form it is easy to access the file from the model.
The problem is in the update form how can handle the preview, delete adding new files to the multiple
file input.
Is there a best practice to solve such thing.
The problem is in the update form how can handle the preview, delete adding new files to the multiple file input. Is there a best practice to solve such thing.
I suggest that you could use jQuery MultiFile.
Here are the steps:
1.Download the jQuery MultiFile:https://multifile.fyneworks.com/#Install
2.Find the download zip file and extract it then move to the project wwwroot/lib folder:
For asp.net core mvc:
View:
<form asp-controller="Home" asp-action="UploadData" enctype="multipart/form-data">
<div>
<input type="file" name="files" multiple="multiple" class="multi with-preview" />
<input type="submit" value="Upload" />
</div>
</form>
#section Scripts
{
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js" type="text/javascript" language="javascript"></script>
<script src="~/lib/multifile-master/jquery.MultiFile.js"></script>
}
Controller:
[HttpPost]
public IActionResult UploadData(List<IFormFile> files)
{
//do your stuff...
return Ok();
}
For asp.net core razor pages:
Index.cshtml:
#page
#model IndexModel
<form asp-page-handler="UploadData" enctype="multipart/form-data">
<div>
<input type="file" name="files" multiple="multiple" class="multi with-preview" />
<input type="submit" value="Upload" />
</div>
</form>
#section Scripts
{
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js" type="text/javascript" language="javascript"></script>
<script src="~/lib/multifile-master/jquery.MultiFile.js"></script>
}
Index.cshtml.cs:
public class IndexModel : PageModel
{
public IActionResult OnGet()
{
return Page();
}
public IActionResult OnPostUploadData(List<IFormFile> files)
{
return Page();
}
}
Result:
I've been using bootstrap4 file input!
to load the images when updating the form I used the following way:
var filesArray = [];
$(document).ready(function ()
{
$("#photos").fileinput("refresh",
{
showUpload: false,
showRemove: false
});
loadPhotos();
setTimeout(function ()
{
if (filesArray.length > 0)
{
$(".file-drop-zone-title").remove();
$('#photos').fileinput('readFiles', filesArray);
}
}, 2500);
});
function loadPhotos()
{
//hddPhotos is a hidden input that I stored the images URLs in
var photosPath = $('#hddPhotos').val();
if (photosPath !== null && photosPath!=='')
{
var photos = jQuery.parseJSON($('#hddPhotos').val());
if (photos.length > 0)
{
var count = photos.length;
for (var i = 0; i < count; i++)
{
getBlobofImage(photos[i]);
}
}
}
}
function getBlobofImage(imagePath)
{
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", imagePath);
xhr.responseType = "blob";//force the HTTP response, response-type header to be blob
xhr.onload = function ()
{
blob = xhr.response;//xhr.response is now a blob object
filesArray.push(new File([blob], /[^/]*$/.exec(imagePath)[0]));
};
xhr.send();
}

MVC 4 File upload in jquery modal dialog window

Im'm working on an MVC/Razor based application
I'm trying to set up a file upload inside a view that is inside a jquery modal dialog box
here's my View code
#using (Html.BeginForm("<MyAction>", "<MyController>", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" id="UploadImage" name="UploadImage" style="width:705px;" />
</div>
<div>
<input id="sbmt" type="submit" value="Save" />
</div>
}
but when i get to my controller action, Request.Files.Count is allways 0
public ActionResult MyAction(Model model){
...
}
What am I missing here?
Thanks
I was able to perform a File Upload in a JQuery Modal Dialog (MVC) by explicitly adding form data to the Ajax Post:
Javascript Code:
// Checking whether FormData is available in browser
if (window.FormData !== undefined) {
var fileUpload = $("#fileInput").get(0);
var files = fileUpload.files;
// Create FormData object
var fileData = new FormData();
// Looping over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
// Adding additional parameters to FormData object
fileData.append('name', $('#nameinput').val());
fileData.append('uniqueID', $('#hiddenFieldUniqueID').val());
$.ajax({
type: 'POST',
contentType: false,
processData: false,
url: '#Url.Action("UploadFile", "YourController")',
data: fileData,
success: function (returnValues) {
$('.ui-dialog-buttonpane').unblock();
if (returnValues["success"] == true) {
bootbox.alert(returnValues["feedback"]);
$(dlg).dialog("close");
}
else {
bootbox.alert(returnValues["feedback"]);
}
},
error: function (returnValue) {
$('.ui-dialog-buttonpane').unblock();
debugger;
bootbox.alert({ message: "Oops - Error Occured!" + returnValue, size: 'small' });
}
});
}
else {
bootbox.alert("Your browser doesnt support the method we are using to upload files (FormData is not supported)");
}
HTML (No form tag required):
<div class="col-md-9">
<label class="btn btn-primary" for="fileInput">
<input id="fileInput" type="file" style="display:none"
onchange="$('#upload-file-info').html(this.files[0].name)">
Select
</label>
<span class='label label-info' id="upload-file-info"></span>
</div>
Controller:
[HttpPost]
public ActionResult UploadFile()
{
YourObjectFile yourObjectFile = null;
try
{
string name = Request.Form["name"];
if (Request.Files.Count > 0)
{
yourObjectFile = new YourObjectFile ();
HttpPostedFileBase file = Request.Files[0];
if (file != null && file.ContentLength > 0)
{
string fileName = file.FileName;
using (var reader = new System.IO.BinaryReader(file.InputStream))
{
yourObjectFile.RawData = reader.ReadBytes(file.ContentLength);
}
}
}
.......
Credit for this approach belongs here: http://www.c-sharpcorner.com/UploadFile/manas1/upload-files-through-jquery-ajax-in-Asp-Net-mvc/

Creating dynamic view from a controller in MVC

I have this controller and view:
public ActionResult DynamicView()
{
return View();
}
_
#model ChatProj.Models.GroupNumber
#{
ViewBag.Title = "DynamicView";
}
<h2>DynamicView</h2>
<fieldset>
<legend>Create a room</legend>
<div class="editor-label">
#Html.LabelFor(model => model.GroupId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.GroupId)
#Html.ValidationMessageFor(model => model.GroupId)
</div>
<input type="submit" value="DynamicView" />
</fieldset>
This is what it looks like on the page.
That's fine and dandy, but I would like to pass that number to a controller, which then passes it to a view. I would like to pass it to this view:
#using PagedList.Mvc;
#using ChatProj.App_Code;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Grupprum 1";
}
<h2>Grupprum 1</h2>
<style>
ul {list-style-type:circle;}
</style>
<div class="container">
<div class="nano chat">
<div class="content">
<ul id="discussion">
</ul>
</div>
</div>
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" disabled="disabled" />
<input type="hidden" id="displayname" />
</div>
#section scripts {
<!--Script references. -->
<!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
<!--Reference the SignalR library. -->
<script src="~/Scripts/jquery.signalR-1.1.3.js"></script>
<script src="~/Scripts/jquery.nanoscroller.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/signalr/hubs"></script>
<!--SignalR script to update the chat page and send messages.-->
<script>
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
$(".nano").nanoScroller();
// Create a function that the hub can call back to display messages.
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
$(document).ready(function () {
$("#sendmessage").removeAttr("disabled");
$('#message').keypress(function (e) {
if (e.keyCode == 13)
$('#sendmessage').click();
});
});
// Get the user name and store it to prepend to messages.
// Set initial focus to message input box.
$('#message').focus();
$.connection.hub.qs = { "room": "Grupprum 1" };
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
}
Specifically I would want it at $.connection.hub.qs = { "room": "Grupprum 1" }; to replace the 1.
So I've created these controllers which are faulty and incomplete:
[HttpPost]
public ActionResult DynamicView(int? roomNumber)
{
return View(GroupRoom(roomNumber));
}
public ActionResult GroupRoom(int roomNumber)
{
return View();
}
Does anyone know how I should change my controllers and views so that I'm able to insert a number in my DynamicGroup view, and get a view back based on the inserted number and the lastly mentioned view?
You could pass the number from the model to the new action just how #Matt Bodily did. But if you want to use a different model on your new view, you can use the below code instead:
public ActionResult GroupRoom(int roomNumber)
{
ViewBag.RoomNumber = roomNumber;
return View();
}
This way, you can use a different model for this page, if you want to. To display this ViewBag on the page, use this code anywhere you want:
#ViewBag.RoomNumber
I hope that helps you out.
How you have it set up the Model.GroupID will be set on the first view so change your controller like this
[HttpPost]
public ActionResult DynamicView(GroupNumber model)
{
//model.GroupId here will be what was selected on the first view
return RedirectToAction("GroupRoom", "Controller", new { GroupId = model.GroupId });
}
public ActionResult GroupRoom(int GroupId)
{
var model = //build your model based on the selected GroupId
return View(model);
}

Add error message if duplicate record exist in MVC Popup Form

I have a popup window called AddNew will display when the user click a button called add New. The button itself has number of field called TRN and DOB. The problem that i have now that i am trying to display error message when the user try to add duplicate TRN but unfortunately no error message display only if the required field is empty.
Is there anyway i could display the duplicate error message in validation summary like displaying in required field and hold all the previous entered value in the form. Please advise. Thank you
Here is the code that i have so far. Thank you
Index.cshtml
<input type="button" id="btnAddNew" style="height:50px; font-size:14px; width:95px; background-color:#3399FF; white-space: normal;" class="k-button" title="AddNew" value="Add New" />
<script type="text/javascript">
$(document).ready(function () {
$('#btnAddNew').click(function () {
window.open('#Url.Action("AddNew", "Details")', 'AddProduct', 'height=' + (window.screen.height - 450) + ',width=950,left=' + (window.screen.width - 5) + ',top=10,status=no,toolbar=no,resizable=yes,scrollbars=yes');
});
});
</script>
AddNew.cshtml (window popup)
#{
Layout = "~/Views/Shared/_LayoutNoMenu.cshtml";
}
<script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
#model HHIMS_Web_App.Models.CModel
#{
ViewBag.Title = "New Product";
}
#using (Html.BeginForm("Create", "Details", FormMethod.Post, new { id = "frmAsset" }))
{
ViewContext.FormContext.ValidationSummaryId = "valSumId";
#Html.ValidationSummary(false, "Please fix the following errors:", new Dictionary<string, object> { { "id", "valSumId" } });
<fieldset id="AddNew">
<div>
<div class="addInfo">
#Html.LabelFor(model => model.TRN)
#Html.EditorFor(model => model.TRN)
#Html.ValidationMessageFor(model => model.TRN, "*")
</div>
<div class="AddSmallBox">
#Html.LabelFor(model => model.DOB)
#Html.EditorFor(model => model.DOB)
#Html.ValidationMessageFor(model => model.DOB, "*")
</div>
</div>
<div>
<div class="smallAddAndCancel">
<input type="button" id="btnCancel" style="height:50px; width:85px; font-size:14px; background-color:#3399FF" class="k-button" title="Cancel" value="Cancel" onclick="window.close()" />
<input type="submit" id="btnSave" style="height:50px; width:85px; font-size:14px; background-color:#3399FF;white-space: normal" class="k-button" title="Save" value="Save"/>
</div>
</div>
</fieldset>
}
<script type="text/javascript">
$(document).ready(function () {
$("#datepicker").closest("span.k-datepicker").width(400);
$('#btnSave').click(function () {
var validation = $("#frmAsset");
if (!validation.valid()) {
return false;
else
{
$.ajax({
type: 'POST',
url: "#Url.Action("Create","Details")",
data: {
TRN: $("#TRN").val(),
DOB: $("#DOB").val(),
},
success: function () {
window.close()
}
});
}
});
});
</script>
Controller:
[HttpPost]
public ActionResult Create(Cmodel)
{
try
{
if (ModelState.IsValid)
{
CheckDuplicateHRNExist(model);
return RedirectToAction("AddNew");
}
if (ModelState.IsValid)
{
HH_DataAccessLayer.Consumers dalModel = new HH_DataAccessLayer.Consumers();
Mapper.CreateMap<CModel, HH_DataAccessLayer.Consumers>();
Mapper.Map(model, dalModel);
return RedirectToAction("Index");
}
}
catch (DbUpdateConcurrencyException e)
{
var entry = e.Entries.Single();
var clientValues = (CModel)entry.Entity;
}
return RedirectToAction("Index");
}
/// <summary>
/// Validate TRN find if no duplicate TRN recorded
/// </summary>
/// <param name="model"></param>
private void CheckDuplicateTRNExist(CModel model)
{
HEntities context = new HEntities();
if (model.TRN != null)
{
var duplicateTRN = context.Consumers.Where(d => d.TRN == model.TRN).FirstOrDefault();
if (duplicateTRN != null)
{
var errorMessage = String.Format("TRN is already exist.", duplicateTRN);
ModelState.AddModelError(string.Empty, errorMessage);
}
}
}
Model
[Required(ErrorMessage = "Please enter TRN")]
[DisplayName("TRN")]
[StringLength(20)]
public string TRN { get; set; }
[Required(ErrorMessage = "Please enter or select Date of Birth")]
[DisplayName("Date Of Birth")]
public DateTime? DOB { get; set; }
If I'm not mistaking, ValidationSummary must be set to true to display custom errors.
Edit: to be complete:
In your AddNew.cshtml file, replace
#Html.ValidationSummary(false, "Please fix the following errors:", new Dictionary<string, object> { { "id", "valSumId" } });
With:
#Html.ValidationSummary(true, "Please fix the following errors:", new Dictionary<string, object> { { "id", "valSumId" } });