Подтвердить что ты не робот

ASP MVC Просмотр в виде JSON

У меня есть приложение MVC с довольно несколькими действиями контроллера, которые вызывается с помощью Ajax (jQuery) и возвращают частичный просмотр контента, который обновляет часть экрана. Но то, что я предпочел бы, это вернуть JSON что-то вроде этого.

return Json(new { 
    Result = true, 
    Message = "Item has been saved", 
    Content = View("Partial") 
});

Где HTML - это просто свойство Json. Это означает, что мне нужно получить HTML-код, который визуализируется методом View. Есть ли простой способ сделать это, несколько примеров, которые я видел, довольно запутаны.

Изменить: этот вопрос изначально был для ASP.NET MVC 1, но если версия 2 упрощает, я бы хотел услышать ответ.

4b9b3361

Ответ 1

Вот ответ! Это небольшое изменение от метода Martin From и, похоже, это работает. Если есть недостающие вещи, можете ли люди вносить какие-либо изменения в код в разделе комментариев. Спасибо.

С вашего контроллера вызывается так:

string HTMLOutput = Utils.RenderPartialToString("~/Views/Setting/IndexMain.ascx", "", items, this.ControllerContext.RequestContext);

Добавьте это в класс

public static string RenderPartialToString(string controlName, object viewData, object model, System.Web.Routing.RequestContext viewContext)
{
     ViewDataDictionary vd = new ViewDataDictionary(viewData);
     ViewPage vp = new ViewPage { ViewData = vd };

     vp.ViewData = vd;
     vp.ViewData.Model = model;
     vp.ViewContext = new ViewContext();
     vp.Url = new UrlHelper(viewContext);

     Control control = vp.LoadControl(controlName);

     vp.Controls.Add(control);

     StringBuilder sb = new StringBuilder();

     using (StringWriter sw = new StringWriter(sb))
     using (HtmlTextWriter tw = new HtmlTextWriter(sw))
     {
         vp.RenderControl(tw);
     }

     return sb.ToString();
}

Ответ 2

NerdDinner имеет некоторые довольно хорошие примеры этого. Здесь находится SearchController в NerdDinner, у которого есть метод под названием SearchByLocation, который возвращает список JsonDinners (исходный код для NerdDinner - это Creative Commons):

namespace NerdDinner.Controllers {

    public class JsonDinner {
        public int      DinnerID    { get; set; }
        public string   Title       { get; set; }
        public double   Latitude    { get; set; }
        public double   Longitude   { get; set; }
        public string   Description { get; set; }
        public int      RSVPCount   { get; set; }
    }

    public class SearchController : Controller {

        IDinnerRepository dinnerRepository;

        //
        // Dependency Injection enabled constructors

        public SearchController()
            : this(new DinnerRepository()) {
        }

        public SearchController(IDinnerRepository repository) {
            dinnerRepository = repository;
        }

        //
        // AJAX: /Search/FindByLocation?longitude=45&latitude=-90

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SearchByLocation(float latitude, float longitude) {

            var dinners = dinnerRepository.FindByLocation(latitude, longitude);

            var jsonDinners = from dinner in dinners
                              select new JsonDinner {
                                  DinnerID = dinner.DinnerID,
                                  Latitude = dinner.Latitude,
                                  Longitude = dinner.Longitude,
                                  Title = dinner.Title,
                                  Description = dinner.Description,
                                  RSVPCount = dinner.RSVPs.Count
                              };

            return Json(jsonDinners.ToList());
        }
    }
}

Ответ 4

Я потратил века, пытаясь сделать то же самое. У меня есть быстрое решение, которое нужно будет продолжить.

ПРИМЕЧАНИЕ. Я вижу уже одну проблему. Любые файлы cookie и другие переменные теряются: (

Что я сделал:

  • Создать новый ActionResult

    public class JsonHtmlViewResult : ViewResult
    {
        public IJsonHtml Data { get; set; }
    
        public override void ExecuteResult(ControllerContext context)
        {
            if (Data == null)
            {
                Data = new DefaultJsonHtml();
            }
    
            using (StringWriter sw = new StringWriter())
            {
                HttpRequest request = HttpContext.Current.Request;
                HttpContext.Current = new HttpContext(request, new HttpResponse(sw));
    
                base.ExecuteResult(context);
    
                Data.HtmlContent = sw.ToString();
            }
    
            // Do the serialization stuff.
            HttpResponseBase response = context.HttpContext.Response;
            response.ClearContent();
            response.ContentType = "application/json";
    
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            response.Write(serializer.Serialize(Data));
        }
    }
    
  • Класс Data​​p >

    public interface IJsonHtml
    {
        String HtmlContent { get; set; }
    }
    
    public class DefaultJsonHtml : IJsonHtml
    {
        public String HtmlContent { get; set; }
    }
    
  • Расширения контроллера

    public static ActionResult JsonHtmlViewResult(this Controller controller, string viewName, string masterName, object model, IJsonHtml data)
    {
        if (model != null)
        {
            controller.ViewData.Model = model;
        }
    
        return new JsonHtmlViewResult
        {
            Data = data,
            ViewName = viewName,
            MasterName = masterName,
            ViewData = controller.ViewData,
            TempData = controller.TempData
        };
    }
    

Ответ 6

Я нашел более свежий ответ с помощью Razor, который может быть полезен http://codepaste.net/8xkoj2

public static string RenderViewToString(string viewPath, object model,ControllerContext context)
{            
    var viewEngineResult = ViewEngines.Engines.FindView(context, viewPath, null);
    var view = viewEngineResult.View;


    context.Controller.ViewData.Model = model;

    string result = String.Empty;
    using (var sw = new StringWriter())
    {

        var ctx = new ViewContext(context, view, 
                                  context.Controller.ViewData, 
                                  context.Controller.TempData, 
                                  sw);
        view.Render(ctx, sw);

        result = sw.ToString();
    }

    return result;
}

Ответ 7

Почему бы не просто статические html-частичные части и захватить все динамическое содержимое из json? Вы должны иметь возможность загружать html файлы с помощью jquery, когда страница загружается или когда требуется достаточно легко.

Эта ссылка на JQuery Ajax дает следующий пример:

//Alert out the results from requesting test.php (HTML or XML, depending on what was returned).
$.get("test.php", function(data){
  alert("Data Loaded: " + data);
});

Ответ 8

Craig,

Посмотрите на это. Джеффри Палермо написал SubController для ASP.NET MVC, который должен выполнить то, что вы хотите:

MvcContrib - теперь с поддержкой SubController для ASP.NET MVC: http://jeffreypalermo.com/blog/mvccontrib-now-with-subcontroller-support/

Ответ 9

Я не знаю, с какого номера версии вы можете это сделать, но в настоящее время вы можете вернуть JSON очень простым способом:

public ActionResult JSONaction()
{
    return Json(data, JsonRequestBehavior);
}

нет необходимости в сложных помощниках и т.д.

данные, конечно, ваши данные из вашей модели JsonRequestBehavior указывает, разрешены ли запросы HTTP GET от клиента. (источник), необязательно DenyGet является поведением по умолчанию, поэтому, если используется в основном JsonRequestBehavior.AllowGet и здесь, почему это там